package cn.stylefeng.guns.modular.storage.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;

import javax.annotation.Resource;

import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo;
import cn.stylefeng.guns.core.util.DateUtil;
import cn.stylefeng.guns.core.util.ExcelWrite;
import cn.stylefeng.guns.modular.basic.entity.BasicCustomer;
import cn.stylefeng.guns.modular.basic.entity.BasicGoods;
import cn.stylefeng.guns.modular.basic.entity.BasicTray;
import cn.stylefeng.guns.modular.basic.model.params.BasicGoodsParam;
import cn.stylefeng.guns.modular.basic.model.params.BasicPositionParam;
import cn.stylefeng.guns.modular.basic.model.params.BasicTrayParam;
import cn.stylefeng.guns.modular.basic.model.result.BasicPositionResult;
import cn.stylefeng.guns.modular.basic.model.result.BasicTrayResult;
import cn.stylefeng.guns.modular.basic.service.BasicCustomerService;
import cn.stylefeng.guns.modular.basic.service.BasicGoodsService;
import cn.stylefeng.guns.modular.basic.service.BasicPositionService;
import cn.stylefeng.guns.modular.basic.service.BasicTrayService;
import cn.stylefeng.guns.modular.order.entity.OrderPut;
import cn.stylefeng.guns.modular.order.model.params.OrderPutDetailedParam;
import cn.stylefeng.guns.modular.order.model.params.OrderPutParam;
import cn.stylefeng.guns.modular.order.model.params.OrderTransportParam;
import cn.stylefeng.guns.modular.order.model.result.OrderPutDetailedResult;
import cn.stylefeng.guns.modular.order.model.result.OrderTransportResult;
import cn.stylefeng.guns.modular.order.service.OrderPutDetailedService;
import cn.stylefeng.guns.modular.order.service.OrderPutService;
import cn.stylefeng.guns.modular.order.service.OrderTransportService;
import cn.stylefeng.guns.modular.rest.storagePut.tarpanBatch;
import cn.stylefeng.guns.modular.storage.entity.StoragePutSingle;
import cn.stylefeng.guns.modular.storage.mapper.StoragePutSingleMapper;
import cn.stylefeng.guns.modular.storage.model.params.StoragePutParam;
import cn.stylefeng.guns.modular.storage.model.params.StoragePutSingleParam;
import cn.stylefeng.guns.modular.storage.model.params.StorageStockParam;
import cn.stylefeng.guns.modular.storage.model.result.StoragePutResult;
import cn.stylefeng.guns.modular.storage.model.result.StoragePutSingleResult;
import cn.stylefeng.guns.modular.storage.model.result.StorageStockResult;
import cn.stylefeng.guns.modular.storage.service.StoragePutService;
import cn.stylefeng.guns.modular.storage.service.StoragePutSingleService;
import cn.stylefeng.guns.modular.storage.service.StorageStockService;
import cn.stylefeng.guns.modular.system.model.params.SysSwitchParam;
import cn.stylefeng.guns.modular.system.model.result.SysSwitchResult;
import cn.stylefeng.guns.modular.system.service.SysSwitchService;
import cn.stylefeng.guns.sys.modular.system.entity.Dept;
import cn.stylefeng.guns.sys.modular.system.entity.User;
import cn.stylefeng.guns.sys.modular.system.service.DeptService;
import cn.stylefeng.guns.sys.modular.system.service.DictService;
import cn.stylefeng.guns.sys.modular.system.service.UserService;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;
/**
 * 入库单明细表 服务实现类
 */
@Service
public class StoragePutSingleServiceImpl extends ServiceImpl<StoragePutSingleMapper, StoragePutSingle> implements StoragePutSingleService {

	@Resource
	private SysSwitchService sysSwitchService;

    @Resource
    private OrderPutDetailedService orderPutDetailedService;

    @Resource
    private BasicGoodsService basicGoodsService;

    @Resource
    private StoragePutSingleService storagePutSingleService;

    @Resource
    private BasicTrayService basicTrayService;

    @Resource
    private StoragePutService storagePutService;

    @Resource
    private UserService userService;

    @Resource
    private DictService dictService;

    @Resource
    private OrderPutService orderPutService;

    @Resource
    private OrderTransportService orderTransportService;

    @Resource
    private BasicPositionService basicPositionService;

    @Resource
    private StorageStockService storageStockService;

    @Override
    public void add(StoragePutSingleParam param){
        StoragePutSingle entity = getEntity(param);
        this.save(entity);
    }

    @Override
    public void delete(StoragePutSingleParam param){
        this.removeById(getKey(param));
    }

    @Override
    public void update(StoragePutSingleParam param){
        StoragePutSingle oldEntity = getOldEntity(param);
        StoragePutSingle newEntity = getEntity(param);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
    }

    @Override
    public StoragePutSingleResult findBySpec(StoragePutSingleParam param){
        return this.baseMapper.findBySpec(param);
    }

    @Override
    public List<StoragePutSingleResult> findListBySpec(StoragePutSingleParam param){
    	return this.baseMapper.findListBySpec(param);
    }

    @Override
    public List<StoragePutSingleResult> findExportToExcelBySpec(StoragePutSingleParam param, Long operateId){
    	return this.baseMapper.findExportToExcelBySpec(param, operateId);
    }

	@Override
	public List<StoragePutSingleResult> customList(StoragePutSingleParam param){
		return this.baseMapper.customList(param);
	}

	@Override
	public List<StoragePutSingleResult> TcustomList(StoragePutSingleParam param){
		return this.baseMapper.TcustomList(param);
	}



    @Override
    public LayuiPageInfo findPageBySpec(StoragePutSingleParam param,String condition){
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.customPageList(pageContext, param,condition);
        return LayuiPageFactory.createPageInfo(page);
    }

	@Override
	public LayuiPageInfo findPageDISTINCTGoods(StoragePutSingleParam storagePutSingleParam) {
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.findPageDISTINCTGoods(pageContext, storagePutSingleParam);
        return LayuiPageFactory.createPageInfo(page);
	}

	@Override
	public LayuiPageInfo findPageworkGoods(StoragePutSingleParam storagePutSingleParam) {
		Page pageContext = getPageContext();
		IPage page = this.baseMapper.findPageworkGoods(pageContext, storagePutSingleParam);
		return LayuiPageFactory.createPageInfo(page);
	}


    private Serializable getKey(StoragePutSingleParam param){
        return param.getId();
    }

    private Page getPageContext() {
        return LayuiPageFactory.defaultPage();
    }

    private StoragePutSingle getOldEntity(StoragePutSingleParam param) {
        return this.getById(getKey(param));
    }

    private StoragePutSingle getEntity(StoragePutSingleParam param) {
        StoragePutSingle entity = new StoragePutSingle();
        ToolUtil.copyProperties(param, entity);
        return entity;
    }

	@Resource
    private DeptService deptService;
	
	/**
	 * 获取所属项目单号前缀
	 * @param user
	 * @return
	 */
	public String getOperateIdOrderPrefix(User user) {
		if(user.getOperateId() != null) {
			Dept dept = new Dept();
			dept.setOperateId(user.getOperateId());
			Dept resdept = deptService.findBySpec(dept);
			if(resdept != null) {
				if(ToolUtil.isNotEmpty(resdept.getOrderPrefix())) {
					return resdept.getOrderPrefix();
				} else {
					return user.getAccount().substring(0, 3);
				}
			} else {
				return null;
			}
		} else {
			return null;
		}
	}
    
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void increaseNew(StoragePutSingleParam storagePutSingleParam,User user) {
		//托盘信息
		BasicTrayParam Tp = new BasicTrayParam();
		BasicTray basicTray = basicTrayService.findByThelastone();

		Tp.setTrayState("OCCUPIED");//托盘状态
		Integer TrayNumber = null;
		Long deliverId = user.getDeliverId();
		Long deptId = user.getDeptId();
		String trayCode = getOperateIdOrderPrefix(user)+"-";
		if (basicTray!=null) {
			TrayNumber = (basicTray.getId()+1);
		} else {
			TrayNumber = 1;
		}
		Tp.setDeliverId(deliverId);
		Tp.setDeptId(deptId);
		
		storagePutSingleParam.setSingleState("NOT_RECEIVED");
		if (ToolUtil.isEmpty(storagePutSingleParam.getRecommend())) {
			storagePutSingleParam.setRecommend(DateUtil.getDate());
		}
		BasicGoods bG = basicGoodsService.getById(storagePutSingleParam.getGoodsId());//商品

		BigDecimal putNum = new BigDecimal(storagePutSingleParam.getPutNum());//数量
		BigDecimal Supportvolume = new BigDecimal(bG.getGoodsSupportvolume());//数量

		BigDecimal u = new BigDecimal(0);//单价
		if (storagePutSingleParam.getUnitprice()!=null&&storagePutSingleParam.getUnitprice()!="") {
			u = new BigDecimal(storagePutSingleParam.getUnitprice());
		} else if(bG.getGoodsCharging()!=null&&bG.getGoodsCharging()!="") {
			u = new BigDecimal(bG.getGoodsCharging());
			storagePutSingleParam.setUnitprice(u.toString());
		} else {
			storagePutSingleParam.setUnitprice(u.toString());
		}
		BigDecimal w = new BigDecimal(bG.getGoodsWeight());//重量
		BigDecimal v = new BigDecimal(bG.getGoodsVolume());//体积
		BigDecimal as= new BigDecimal(0);
		
		if (putNum.subtract(Supportvolume).compareTo(as)== -1) {//判断一托是否可以装下全部
			if (w!=null) {
				storagePutSingleParam.setPutWeight((putNum.multiply(w)).toString());//应入重量
			}
			if (v!=null) {
				storagePutSingleParam.setDetailedPutvolume((putNum.multiply(v)).toString());//应入体积
			}
			if (u!=null) {
				storagePutSingleParam.setSingleMoney((putNum.multiply(u)).toString());//金额
			}
			storagePutSingleParam.setPutBalenum(putNum.toString());//应入大包数
			storagePutSingleParam.setPutNum(putNum.toString());//应入数量

			BasicTrayParam trayParam = new BasicTrayParam();
			trayParam.setDeliverId(deliverId);
			trayParam.setDeptId(deptId);
			trayParam.setTrayState("IDLE");
			BasicTrayResult basicTrayResult = basicTrayService.findBySpec(trayParam,user.getOperateId());
			if (basicTrayResult != null) {
				storagePutSingleParam.setTrayNumber(basicTrayResult.getTrayNumber());
				basicTrayResult.setTrayState("OCCUPIED");
				ToolUtil.copyProperties(basicTrayResult, trayParam);
				basicTrayService.update(trayParam);
			} else {
				Tp.setTrayNumber(trayCode+TrayNumber);
				basicTrayService.add(Tp);
				storagePutSingleParam.setTrayNumber(trayCode+TrayNumber);//托盘编号
			}
			this.add(storagePutSingleParam);//添加入库单明细
		} else {//一托装不下
			//默认整托
			List<BasicTray> tList = new ArrayList<BasicTray>();
			List<StoragePutSingle> sList = new ArrayList<StoragePutSingle>();
			StoragePutSingle putSingle = new StoragePutSingle();
			BasicTray bTray = new BasicTray();
			storagePutSingleParam.setPutBalenum(String.valueOf(Supportvolume));//应入大包数
			storagePutSingleParam.setPutNum(String.valueOf(Supportvolume));//应入数量
			if (w!=null) {
				storagePutSingleParam.setPutWeight(String.valueOf(w.multiply(Supportvolume)));//应入重量
			}
			if (v!=null) {
				storagePutSingleParam.setDetailedPutvolume(String.valueOf(v.multiply(Supportvolume)));//应入体积
			}
			if (u!=null) {
				storagePutSingleParam.setSingleMoney(String.valueOf(u.multiply(Supportvolume)));//金额
			}
			while (putNum.compareTo(as)==1) {
				if (putNum.subtract(Supportvolume).compareTo(as)==-1||putNum.subtract(Supportvolume).compareTo(as)==0) {
					if (w!=null) {
						storagePutSingleParam.setPutWeight(String.valueOf(w.multiply(putNum)));//应入重量
					}
					if (v!=null) {
						storagePutSingleParam.setDetailedPutvolume(String.valueOf(v.multiply(putNum)));//应入体积
					}
					if (u!=null) {
						storagePutSingleParam.setSingleMoney(String.valueOf(u.multiply(putNum)));//金额
					}
					storagePutSingleParam.setPutBalenum(String.valueOf(putNum));//应入大包数
					storagePutSingleParam.setPutNum(String.valueOf(putNum));//应入数量
					BasicTrayParam trayParam = new BasicTrayParam();
					trayParam.setDeliverId(deliverId);
					trayParam.setDeptId(deptId);
					trayParam.setTrayState("IDLE");
					BasicTrayResult basicTrayResult = basicTrayService.findBySpec(trayParam,user.getOperateId());
					if (basicTrayResult != null) {
						storagePutSingleParam.setTrayNumber(basicTrayResult.getTrayNumber());
						basicTrayResult.setTrayState("OCCUPIED");
						ToolUtil.copyProperties(basicTrayResult, trayParam);
						basicTrayService.update(trayParam);
					} else {
						Tp.setTrayNumber(trayCode+TrayNumber);
						storagePutSingleParam.setTrayNumber(trayCode+TrayNumber);//托盘编号
						TrayNumber++;
						ToolUtil.copyProperties(Tp,bTray);
						tList.add(bTray);
						bTray = new BasicTray();
					}
					putNum = as;
				} else {
					BasicTrayParam trayParam = new BasicTrayParam();
					trayParam.setDeliverId(deliverId);
					trayParam.setDeptId(deptId);
					trayParam.setTrayState("IDLE");
					BasicTrayResult basicTrayResult = basicTrayService.findBySpec(trayParam,user.getOperateId());
					if (basicTrayResult != null) {
						storagePutSingleParam.setTrayNumber(basicTrayResult.getTrayNumber());
						basicTrayResult.setTrayState("OCCUPIED");
						ToolUtil.copyProperties(basicTrayResult, trayParam);
						basicTrayService.update(trayParam);
					} else {
						Tp.setTrayNumber(trayCode+TrayNumber);
						storagePutSingleParam.setTrayNumber(trayCode+TrayNumber);//托盘编号
						TrayNumber++;
						ToolUtil.copyProperties(Tp,bTray);
						tList.add(bTray);
						bTray = new BasicTray();
					}

					BigDecimal putNum2	=  putNum.subtract(Supportvolume);
					putNum = putNum2;

				}
				ToolUtil.copyProperties(storagePutSingleParam,putSingle);
				sList.add(putSingle);
				putSingle = new StoragePutSingle();
			}
			if (sList.size()>0) {
				this.saveBatchList(sList);//保存list

				if (tList.size()>0) {
					basicTrayService.saveBatchList(tList);
				}
			}
		}
	}
    
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void increase(StoragePutSingleParam storagePutSingleParam) {
		//托盘信息
		BasicTrayParam Tp = new BasicTrayParam();
		BasicTray basicTray = basicTrayService.findByThelastone();

		Tp.setTrayState("OCCUPIED");//托盘状态
		Integer TrayNumber = null;
		if (basicTray!=null) {
			TrayNumber = (basicTray.getId()+1);
		} else {
			TrayNumber = 1;
		}
		Tp.setDeliverId(userService.getDeliverId());
		Tp.setDeptId(userService.getDeptId());
		
		storagePutSingleParam.setSingleState("NOT_STARTED");
		if (ToolUtil.isEmpty(storagePutSingleParam.getRecommend())) {
			storagePutSingleParam.setRecommend(DateUtil.getDate());
		}
		BasicGoods bG = basicGoodsService.getById(storagePutSingleParam.getGoodsId());//商品

		BigDecimal putNum = new BigDecimal(storagePutSingleParam.getPutNum());//数量
		BigDecimal Supportvolume = new BigDecimal(bG.getGoodsSupportvolume());//数量

		BigDecimal u = new BigDecimal(0);//单价
		if (storagePutSingleParam.getUnitprice()!=null&&storagePutSingleParam.getUnitprice()!="") {
			u = new BigDecimal(storagePutSingleParam.getUnitprice());
		} else if(bG.getGoodsCharging()!=null&&bG.getGoodsCharging()!="") {
			u = new BigDecimal(bG.getGoodsCharging());
			storagePutSingleParam.setUnitprice(u.toString());
		} else {
			storagePutSingleParam.setUnitprice(u.toString());
		}
		BigDecimal w = new BigDecimal(bG.getGoodsWeight());//重量
		BigDecimal v = new BigDecimal(bG.getGoodsVolume());//体积
		BigDecimal as= new BigDecimal(0);
		
		if (putNum.subtract(Supportvolume).compareTo(as)== -1) {//判断一托是否可以装下全部
			if (w!=null) {
				storagePutSingleParam.setPutWeight((putNum.multiply(w)).toString());//应入重量
			}
			if (v!=null) {
				storagePutSingleParam.setDetailedPutvolume((putNum.multiply(v)).toString());//应入体积
			}
			if (u!=null) {
				storagePutSingleParam.setSingleMoney((putNum.multiply(u)).toString());//金额
			}
			storagePutSingleParam.setPutBalenum(putNum.toString());//应入大包数
			storagePutSingleParam.setPutNum(putNum.toString());//应入数量

			Tp.setTrayNumber("T-"+TrayNumber);
			basicTrayService.add(Tp);
			storagePutSingleParam.setTrayNumber("T-"+TrayNumber);//托盘编号
			this.add(storagePutSingleParam);//添加入库单明细
		} else {//一托装不下
			//默认整托
			List<BasicTray> tList = new ArrayList<BasicTray>();
			List<StoragePutSingle> sList = new ArrayList<StoragePutSingle>();
			StoragePutSingle putSingle = new StoragePutSingle();
			BasicTray bTray = new BasicTray();
			storagePutSingleParam.setPutBalenum(String.valueOf(Supportvolume));//应入大包数
			storagePutSingleParam.setPutNum(String.valueOf(Supportvolume));//应入数量
			if (w!=null) {
				storagePutSingleParam.setPutWeight(String.valueOf(w.multiply(Supportvolume)));//应入重量
			}
			if (v!=null) {
				storagePutSingleParam.setDetailedPutvolume(String.valueOf(v.multiply(Supportvolume)));//应入体积
			}
			if (u!=null) {
				storagePutSingleParam.setSingleMoney(String.valueOf(u.multiply(Supportvolume)));//金额
			}
			while (putNum.compareTo(as)==1) {
				if (putNum.subtract(Supportvolume).compareTo(as)==-1||putNum.subtract(Supportvolume).compareTo(as)==0) {
					if (w!=null) {
						storagePutSingleParam.setPutWeight(String.valueOf(w.multiply(putNum)));//应入重量
					}
					if (v!=null) {
						storagePutSingleParam.setDetailedPutvolume(String.valueOf(v.multiply(putNum)));//应入体积
					}
					if (u!=null) {
						storagePutSingleParam.setSingleMoney(String.valueOf(u.multiply(putNum)));//金额
					}
					storagePutSingleParam.setPutBalenum(String.valueOf(putNum));//应入大包数
					storagePutSingleParam.setPutNum(String.valueOf(putNum));//应入数量
					storagePutSingleParam.setTrayNumber("T-"+TrayNumber);
					Tp.setTrayNumber("T-"+TrayNumber);
					putNum = as;
				} else {
					storagePutSingleParam.setTrayNumber("T-"+TrayNumber);
					Tp.setTrayNumber("T-"+TrayNumber);

					BigDecimal putNum2	=  putNum.subtract(Supportvolume);
					putNum = putNum2;

				}
				TrayNumber++;
				ToolUtil.copyProperties(Tp,bTray);
				ToolUtil.copyProperties(storagePutSingleParam,putSingle);
				tList.add(bTray);
				sList.add(putSingle);
				bTray = new BasicTray();
				putSingle = new StoragePutSingle();
			}
			if (tList.size()>0&&sList.size()>0) {
				this.saveBatchList(sList);//保存list
				basicTrayService.saveBatchList(tList);
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class,timeout=2000)
	public void productionPutSingleNew(OrderPut orderPut,User user) {
		//新增入库单
		StoragePutParam storagePutParam = new StoragePutParam();
		Long deliverId = user.getDeliverId();
		Long deptId = user.getDeptId();
		String trayCode = getOperateIdOrderPrefix(user)+"-";
		storagePutParam.setStorageNumber(orderPut.getPutCustomerNumber());
		storagePutParam.setPutNumber(orderPut.getPutNumber());//入库订单编号
		storagePutParam.setCustomerId(orderPut.getPutCustomerId());//客户id
		storagePutParam.setCustomerName(orderPut.getPutCustomerName());//客户名称
		storagePutParam.setCustomerNumber(orderPut.getPutCustomerNumber());//客户单号
		storagePutParam.setWarehouseId(orderPut.getWarehouseId());//仓库id
		storagePutParam.setWarehouseName(orderPut.getWarehouseName());//仓库名称
		storagePutParam.setDeliverId(deliverId);
		storagePutParam.setDeptId(deptId);
		storagePutParam.setBillstate("INCOMPLETE");//入库单状态
		storagePutService.add(storagePutParam);

		//托盘信息
		BasicTrayParam Tp = new BasicTrayParam();
		BasicTray basicTray = basicTrayService.findByThelastone();
		Tp.setTrayState("OCCUPIED");//托盘状态
		int TrayNumber = 0;
		if (basicTray!=null) {
			TrayNumber = (basicTray.getId()+1);
		} else {
			TrayNumber = 1;
		}
		Tp.setDeliverId(deliverId);
		Tp.setDeptId(deptId);
		
		//新增入库单明细
		OrderPutDetailedParam putDetailedParam = new OrderPutDetailedParam();
		putDetailedParam.setPutDetailedNumber(orderPut.getPutNumber());
		List<OrderPutDetailedResult> putDlist = orderPutDetailedService.totalListByGandPSpec(putDetailedParam);//入库订单明细
		
		List<BasicPositionParam> totallist = new ArrayList<BasicPositionParam>();//合计推荐库位的托数量
		List<StoragePutSingle> usableList = new ArrayList<StoragePutSingle>();//库位  商品  数量(匹配空库位集合)
		boolean recommend = false;
		
		for (OrderPutDetailedResult PutD : putDlist) {
			BasicGoods bG = basicGoodsService.getById(PutD.getDetailedGoodsnum());//商品
			BigDecimal detailedPutnum = new BigDecimal(PutD.getDetailedPutnum());//入库数量
			BigDecimal Supportvolume = new BigDecimal(bG.getGoodsSupportvolume());//每托存量
			BigDecimal w = new BigDecimal(bG.getGoodsWeight());//重量
			BigDecimal v = new BigDecimal(bG.getGoodsVolume());//体积
			BigDecimal u = new BigDecimal(bG.getGoodsCharging());//单价compareTo
			BigDecimal as = new BigDecimal(0);
			
			if (detailedPutnum.subtract(Supportvolume).compareTo(as)== -1) {//判断一托是否可以装下全部
				StoragePutSingleParam s = new StoragePutSingleParam();
				boolean packfull = false;
				for (int i = 0; i < usableList.size(); i++) {
					if (usableList.get(i).getGoodsId().longValue()==PutD.getDetailedGoodsnum().longValue()) {
						BigDecimal putNum = new BigDecimal(usableList.get(i).getPutNum());
						BigDecimal sub = new BigDecimal(1);
						if (putNum.compareTo(as)==1) {
							putNum = putNum.subtract(sub);
							StoragePutSingle sps = usableList.get(i);
							sps.setPutNum(putNum.toString());
							usableList.set(i, sps);
							s.setPositionNumber(sps.getPositionNumber());
							packfull = true;
							break;
						}
					}
				}
				prepare(s,PutD,orderPut.getWarehouseId(),totallist,packfull,recommend,user,bG);//生成入库单明细，推荐库位
				if (w!=null) {
					s.setPutWeight(String.valueOf(w.multiply(detailedPutnum)));//应入重量
				}
				if (v!=null) {
					s.setDetailedPutvolume(String.valueOf(v.multiply(detailedPutnum)));//应入体积
				}
				if (u!=null) {
					s.setSingleMoney(String.valueOf(u.multiply(detailedPutnum)));//金额
				}
				s.setStorageNumber(storagePutParam.getStorageNumber());//入库单编号
				s.setPutBalenum(String.valueOf(detailedPutnum));//应入大包数
				s.setPutNum(String.valueOf(detailedPutnum));//应入数量
				BasicTrayParam trayParam = new BasicTrayParam();
				trayParam.setDeliverId(deliverId);
				trayParam.setDeptId(deptId);
				trayParam.setTrayState("IDLE");
				BasicTrayResult basicTrayResult = basicTrayService.findBySpec(trayParam,user.getOperateId());
				if (basicTrayResult != null) {
					s.setTrayNumber(basicTrayResult.getTrayNumber());
					basicTrayResult.setTrayState("OCCUPIED");
					ToolUtil.copyProperties(basicTrayResult, trayParam);
					basicTrayService.update(trayParam);
				} else {
					Tp.setTrayNumber(trayCode+TrayNumber);
					basicTrayService.add(Tp);
					s.setTrayNumber(trayCode+TrayNumber);//托盘编号
				}
				this.add(s);//添加入库单明细
				TrayNumber++;
			} else {
				List<BasicTray> tList = new ArrayList<BasicTray>();
				List<StoragePutSingle> sList = new ArrayList<StoragePutSingle>();
				StoragePutSingle putSingle = new StoragePutSingle();
				BasicTray bTray = new BasicTray();
				StoragePutSingleParam s = new StoragePutSingleParam();
				while (detailedPutnum.compareTo(as)==1) {
					if (detailedPutnum.subtract(Supportvolume).compareTo(as)== -1||detailedPutnum.subtract(Supportvolume).compareTo(as)== 0) {
						boolean packfull = false;
						for (int i = 0; i < usableList.size(); i++) {
							if (usableList.get(i).getGoodsId().longValue()==PutD.getDetailedGoodsnum().longValue()) {
								BigDecimal putNum = new BigDecimal(usableList.get(i).getPutNum());
								BigDecimal sub = new BigDecimal(1);
								if (putNum.compareTo(as)==1) {
									putNum = putNum.subtract(sub);
									StoragePutSingle sps = usableList.get(i);
									sps.setPutNum(putNum.toString());
									usableList.set(i, sps);
									s.setPositionNumber(sps.getPositionNumber());
									packfull = true;
									break;
								}
							}
						}
						prepare(s,PutD,orderPut.getWarehouseId(),totallist,packfull,recommend,user,bG);//生成入库单明细，推荐库位
						s.setStorageNumber(storagePutParam.getStorageNumber());//入库单编号
						//剩余刚好一托 够装下
						if (w!=null) {
							s.setPutWeight(String.valueOf(w.multiply(detailedPutnum)));//应入重量
						}
						if (v!=null) {
							s.setDetailedPutvolume(String.valueOf(v.multiply(detailedPutnum)));//应入体积
						}
						if (u!=null) {
							s.setSingleMoney(String.valueOf(u.multiply(detailedPutnum)));//金额
						}
						s.setPutBalenum(String.valueOf(detailedPutnum));//应入大包数
						s.setPutNum(String.valueOf(detailedPutnum));//应入数量
						BasicTrayParam trayParam = new BasicTrayParam();
						trayParam.setDeliverId(deliverId);
						trayParam.setDeptId(deptId);
						trayParam.setTrayState("IDLE");
						BasicTrayResult basicTrayResult = basicTrayService.findBySpec(trayParam,user.getOperateId());
						if (basicTrayResult != null) {
							s.setTrayNumber(basicTrayResult.getTrayNumber());
							basicTrayResult.setTrayState("OCCUPIED");
							ToolUtil.copyProperties(basicTrayResult, trayParam);
							basicTrayService.update(trayParam);
						} else {
							Tp.setTrayNumber(trayCode+TrayNumber);
							s.setTrayNumber(trayCode+TrayNumber);//托盘编号
							TrayNumber++;
							ToolUtil.copyProperties(Tp,bTray);
							tList.add(bTray);
							bTray = new BasicTray();
						}
						detailedPutnum = new BigDecimal(0);
					} else {
						//整托
						boolean packfull = false;
						for (int i = 0; i < usableList.size(); i++) {
							if (usableList.get(i).getGoodsId().longValue()==PutD.getDetailedGoodsnum().longValue()) {
								BigDecimal putNum = new BigDecimal(usableList.get(i).getPutNum());
								BigDecimal sub = new BigDecimal(1);
								if (putNum.compareTo(as)==1) {
									putNum = putNum.subtract(sub);
									StoragePutSingle sps = usableList.get(i);
									sps.setPutNum(putNum.toString());
									usableList.set(i, sps);
									s.setPositionNumber(sps.getPositionNumber());
									packfull = true;
									break;
								}
							}
						}
						prepare(s,PutD,orderPut.getWarehouseId(),totallist,packfull,recommend,user,bG);//生成入库单明细，推荐库位
						s.setStorageNumber(storagePutParam.getStorageNumber());//入库单编号
						if (w!=null) {
							s.setPutWeight(String.valueOf(w.multiply(Supportvolume)));//应入重量
						}
						if (v!=null) {
							s.setDetailedPutvolume(String.valueOf(v.multiply(Supportvolume)));//应入体积
						}
						if (u!=null) {
							s.setSingleMoney(String.valueOf(u.multiply(Supportvolume)));//金额
						}
						s.setPutBalenum(String.valueOf(Supportvolume));//应入大包数
						s.setPutNum(String.valueOf(Supportvolume));//应入数量
						BasicTrayParam trayParam = new BasicTrayParam();
						trayParam.setDeliverId(deliverId);
						trayParam.setDeptId(deptId);
						trayParam.setTrayState("IDLE");
						BasicTrayResult basicTrayResult = basicTrayService.findBySpec(trayParam,user.getOperateId());
						if (basicTrayResult != null) {
							s.setTrayNumber(basicTrayResult.getTrayNumber());
							basicTrayResult.setTrayState("OCCUPIED");
							ToolUtil.copyProperties(basicTrayResult, trayParam);
							basicTrayService.update(trayParam);
						} else {
							Tp.setTrayNumber(trayCode+TrayNumber);
							s.setTrayNumber(trayCode+TrayNumber);//托盘编号
							TrayNumber++;
							ToolUtil.copyProperties(Tp,bTray);
							tList.add(bTray);
							bTray = new BasicTray();
						}
						BigDecimal detailedPutnum2	=  detailedPutnum.subtract(Supportvolume);
						detailedPutnum = detailedPutnum2;
					}
					ToolUtil.copyProperties(s,putSingle);
					sList.add(putSingle);
					putSingle = new StoragePutSingle();
					s = new StoragePutSingleParam();
				}
				if (sList.size()>0) {
					//批量保存入库单名 ，托盘
                    this.saveBatchList(sList);
                    if (tList.size()>0) {
                    	basicTrayService.saveBatchList(tList);
                    }
					for (int i = 0; i < sList.size(); i++) {
						for (int j = 0; j < totallist.size(); j++) {
							if (sList.get(i).getPositionNumber().equals(totallist.get(j).getPositionNumber())) {
								BigDecimal putNum = new BigDecimal(1);
								BigDecimal traySize = new BigDecimal(totallist.get(j).getTraySize());
								traySize = traySize.subtract(putNum);
								BasicPositionParam param = totallist.get(j);
								param.setTraySize(traySize.toString());
								totallist.set(j, param);
							}
						}
					}
				}
			}
		}
		//更新入库单
		orderPut.setBillstate("PENDING_INBOUND");
		OrderPutParam param = new OrderPutParam();
        ToolUtil.copyProperties(orderPut,param);
		orderPutService.update(param);
		//生成货运单
		if ("On-Site Pickup".equals(param.getPutMode())) {
			orderTransportService.updateTransport(param);
		}
	}
	
    @Resource
    private BasicCustomerService basicCustomerService;

	@Override
	@Transactional(rollbackFor = Exception.class,timeout=50)
	public ResponseData productionPutSingle(OrderPut orderPut) {
        BasicCustomer c = basicCustomerService.getById(orderPut.getPutCustomerId());
		//新增入库单
		StoragePutParam storagePutParam = new StoragePutParam();
		User user = userService.getcurrentUser();
		Long deliverId = user.getDeliverId();
		Long deptId = user.getDeptId();
		String trayCode = getOperateIdOrderPrefix(user)+"-";
		storagePutParam.setStorageNumber(orderPut.getPutCustomerNumber());
		storagePutParam.setPutNumber(orderPut.getPutNumber());//入库订单编号
		storagePutParam.setCustomerId(orderPut.getPutCustomerId());//客户id
		storagePutParam.setCustomerName(orderPut.getPutCustomerName());//客户名称
		storagePutParam.setCustomerNumber(orderPut.getPutCustomerNumber());//客户单号
		storagePutParam.setWarehouseId(orderPut.getWarehouseId());//仓库id
		storagePutParam.setWarehouseName(orderPut.getWarehouseName());//仓库名称
		storagePutParam.setDeliverId(deliverId);
		storagePutParam.setDeptId(deptId);
		storagePutParam.setBillstate("INCOMPLETE");//入库单状态
		storagePutService.add(storagePutParam);

		//托盘信息
		BasicTrayParam Tp = new BasicTrayParam();
		BasicTray basicTray = basicTrayService.findByThelastone();
		Tp.setTrayState("OCCUPIED");//托盘状态
		int TrayNumber = 0;
		if (basicTray!=null) {
			TrayNumber = (basicTray.getId()+1);
		} else {
			TrayNumber = 1;
		}
		Tp.setDeliverId(deliverId);
		Tp.setDeptId(deptId);
		
		//新增入库单明细
		OrderPutDetailedParam putDetailedParam = new OrderPutDetailedParam();
		putDetailedParam.setPutDetailedNumber(orderPut.getPutNumber());
		List<OrderPutDetailedResult> putDlist = orderPutDetailedService.totalListByGandPSpec(putDetailedParam);//入库订单明细
		
		List<BasicPositionParam> totallist = new ArrayList<BasicPositionParam>();//合计推荐库位的托数量
		List<StoragePutSingle> usableList = new ArrayList<StoragePutSingle>();//库位  商品  数量(匹配空库位集合)
		//匹配可以装满的  空库位
		//匹配空库位  开关
		SysSwitchParam dParam = new SysSwitchParam();
		dParam.setCode("Empty_location");
		dParam.setDeliverId(deliverId);
		dParam.setDeptId(deptId);
		SysSwitchResult dResult = sysSwitchService.findBySpec(dParam,user.getOperateId());
		if (dResult!=null) {
			if (ToolUtil.isNotEmpty(dResult.getOperation())) {
				if ("Y".equals(dResult.getOperation())) {
					List<OrderPutDetailedResult> putlist = putDlist;
					List<OrderPutDetailedResult> totalputDlist = orderPutDetailedService.totalListBySpec(putDetailedParam);//入库订单明细 合计商品
					packfulls(putlist,totalputDlist,orderPut.getWarehouseId(),totallist,usableList,user);
				}
			}
		}
		//入库推荐  开关
		dParam.setCode("Recommend");
		SysSwitchResult dResult2 = sysSwitchService.findBySpec(dParam,user.getOperateId());
		boolean recommend = false;
		if (dResult2!=null) {
			if (ToolUtil.isNotEmpty(dResult2.getOperation())) {
				if ("Y".equals(dResult2.getOperation())) {
					recommend = true;
				}
			}
		}
		
		for (OrderPutDetailedResult PutD : putDlist) {
			BigDecimal yibai = new BigDecimal("100");
			BasicGoods bG = basicGoodsService.getById(PutD.getDetailedGoodsnum());//商品
			BigDecimal detailedPutnum = new BigDecimal(PutD.getDetailedPutnum());//入库数量
			BigDecimal Supportvolume = new BigDecimal(bG.getGoodsSupportvolume());//每托存量
			BigDecimal dsdiv = detailedPutnum.divide(Supportvolume,2, BigDecimal.ROUND_HALF_DOWN);
			if(dsdiv.compareTo(yibai) == 1) {
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚失误
				return ResponseData.error(bG.getGoodsNumber()+"Generated pallets exceed 100. Please check if the maintained quantity per pallet for commodities is correct.");
			}
			BigDecimal w = new BigDecimal(bG.getGoodsWeight());//重量
			BigDecimal v = new BigDecimal(bG.getGoodsVolume());//体积
			BigDecimal u = new BigDecimal(bG.getGoodsCharging());//单价compareTo
			BigDecimal as = new BigDecimal("0");
			
			if (detailedPutnum.subtract(Supportvolume).compareTo(as)== -1) {//判断一托是否可以装下全部
				StoragePutSingleParam s = new StoragePutSingleParam();
				boolean packfull = false;
				for (int i = 0; i < usableList.size(); i++) {
					if (usableList.get(i).getGoodsId().longValue()==PutD.getDetailedGoodsnum().longValue()) {
						BigDecimal putNum = new BigDecimal(usableList.get(i).getPutNum());
						BigDecimal sub = new BigDecimal(1);
						if (putNum.compareTo(as)==1) {
							putNum = putNum.subtract(sub);
							StoragePutSingle sps = usableList.get(i);
							sps.setPutNum(putNum.toString());
							usableList.set(i, sps);
							s.setPositionNumber(sps.getPositionNumber());
							packfull = true;
							break;
						}
					}
				}
				prepare(s,PutD,orderPut.getWarehouseId(),totallist,packfull,recommend,user,bG);//生成入库单明细，推荐库位
				if (w!=null) {
					s.setPutWeight(String.valueOf(w.multiply(detailedPutnum).setScale(3, BigDecimal.ROUND_HALF_DOWN)));//应入重量
				}
				if (v!=null) {
					s.setDetailedPutvolume(String.valueOf(v.multiply(detailedPutnum).setScale(4, BigDecimal.ROUND_HALF_DOWN)));//应入体积
				}
				if (u!=null) {
					s.setSingleMoney(String.valueOf(u.multiply(detailedPutnum).setScale(3, BigDecimal.ROUND_HALF_DOWN)));//金额
				}
				s.setStorageNumber(storagePutParam.getStorageNumber());//入库单编号
				s.setPutBalenum(String.valueOf(detailedPutnum));//应入大包数
				s.setPutNum(String.valueOf(detailedPutnum));//应入数量
				BasicTrayParam trayParam = new BasicTrayParam();
				trayParam.setDeliverId(deliverId);
				trayParam.setDeptId(deptId);
				trayParam.setTrayState("IDLE");
				BasicTrayResult basicTrayResult = basicTrayService.findBySpec(trayParam,user.getOperateId());
				if (basicTrayResult != null) {
					s.setTrayNumber(basicTrayResult.getTrayNumber());
					basicTrayResult.setTrayState("OCCUPIED");
					ToolUtil.copyProperties(basicTrayResult, trayParam);
					basicTrayService.update(trayParam);
				} else {
					Tp.setTrayNumber(trayCode+TrayNumber);
					basicTrayService.add(Tp);
					s.setTrayNumber(trayCode+TrayNumber);//托盘编号
				}
				this.add(s);//添加入库单明细
				TrayNumber++;
			} else {
				List<BasicTray> tList = new ArrayList<BasicTray>();
				List<StoragePutSingle> sList = new ArrayList<StoragePutSingle>();
				StoragePutSingle putSingle = new StoragePutSingle();
				BasicTray bTray = new BasicTray();
				StoragePutSingleParam s = new StoragePutSingleParam();
				while (detailedPutnum.compareTo(as)==1) {
					if (detailedPutnum.subtract(Supportvolume).compareTo(as)== -1||detailedPutnum.subtract(Supportvolume).compareTo(as)== 0) {
						boolean packfull = false;
						for (int i = 0; i < usableList.size(); i++) {
							if (usableList.get(i).getGoodsId().longValue()==PutD.getDetailedGoodsnum().longValue()) {
								BigDecimal putNum = new BigDecimal(usableList.get(i).getPutNum());
								BigDecimal sub = new BigDecimal(1);
								if (putNum.compareTo(as)==1) {
									putNum = putNum.subtract(sub);
									StoragePutSingle sps = usableList.get(i);
									sps.setPutNum(putNum.toString());
									usableList.set(i, sps);
									s.setPositionNumber(sps.getPositionNumber());
									packfull = true;
									break;
								}
							}
						}
						prepare(s,PutD,orderPut.getWarehouseId(),totallist,packfull,recommend,user,bG);//生成入库单明细，推荐库位
						s.setStorageNumber(storagePutParam.getStorageNumber());//入库单编号
						//剩余刚好一托 够装下
						if (w!=null) {
							s.setPutWeight(String.valueOf(w.multiply(detailedPutnum).setScale(3, BigDecimal.ROUND_HALF_DOWN)));//应入重量
						}
						if (v!=null) {
							s.setDetailedPutvolume(String.valueOf(v.multiply(detailedPutnum).setScale(4, BigDecimal.ROUND_HALF_DOWN)));//应入体积
						}
						if (u!=null) {
							s.setSingleMoney(String.valueOf(u.multiply(detailedPutnum).setScale(3, BigDecimal.ROUND_HALF_DOWN)));//金额
						}
						s.setPutBalenum(String.valueOf(detailedPutnum));//应入大包数
						s.setPutNum(String.valueOf(detailedPutnum));//应入数量
						BasicTrayParam trayParam = new BasicTrayParam();
						trayParam.setDeliverId(deliverId);
						trayParam.setDeptId(deptId);
						trayParam.setTrayState("IDLE");
						BasicTrayResult basicTrayResult = basicTrayService.findBySpec(trayParam,user.getOperateId());
						if (basicTrayResult != null) {
							s.setTrayNumber(basicTrayResult.getTrayNumber());
							basicTrayResult.setTrayState("OCCUPIED");
							ToolUtil.copyProperties(basicTrayResult, trayParam);
							basicTrayService.update(trayParam);
						} else {
							Tp.setTrayNumber(trayCode+TrayNumber);
							s.setTrayNumber(trayCode+TrayNumber);//托盘编号
							TrayNumber++;
							ToolUtil.copyProperties(Tp,bTray);
							tList.add(bTray);
							bTray = new BasicTray();
						}
						detailedPutnum = new BigDecimal(0);
					} else {
						//整托
						boolean packfull = false;
						for (int i = 0; i < usableList.size(); i++) {
							if (usableList.get(i).getGoodsId().longValue()==PutD.getDetailedGoodsnum().longValue()) {
								BigDecimal putNum = new BigDecimal(usableList.get(i).getPutNum());
								BigDecimal sub = new BigDecimal(1);
								if (putNum.compareTo(as)==1) {
									putNum = putNum.subtract(sub);
									StoragePutSingle sps = usableList.get(i);
									sps.setPutNum(putNum.toString());
									usableList.set(i, sps);
									s.setPositionNumber(sps.getPositionNumber());
									packfull = true;
									break;
								}
							}
						}
						prepare(s,PutD,orderPut.getWarehouseId(),totallist,packfull,recommend,user,bG);//生成入库单明细，推荐库位
						s.setStorageNumber(storagePutParam.getStorageNumber());//入库单编号
						if (w!=null) {
							s.setPutWeight(String.valueOf(w.multiply(Supportvolume).setScale(3, BigDecimal.ROUND_HALF_DOWN)));//应入重量
						}
						if (v!=null) {
							s.setDetailedPutvolume(String.valueOf(v.multiply(Supportvolume).setScale(4, BigDecimal.ROUND_HALF_DOWN)));//应入体积
						}
						if (u!=null) {
							s.setSingleMoney(String.valueOf(u.multiply(Supportvolume).setScale(3, BigDecimal.ROUND_HALF_DOWN)));//金额
						}
						s.setPutBalenum(String.valueOf(Supportvolume));//应入大包数
						s.setPutNum(String.valueOf(Supportvolume));//应入数量
						BasicTrayParam trayParam = new BasicTrayParam();
						trayParam.setDeliverId(deliverId);
						trayParam.setDeptId(deptId);
						trayParam.setTrayState("IDLE");
						BasicTrayResult basicTrayResult = basicTrayService.findBySpec(trayParam,user.getOperateId());
						if (basicTrayResult != null) {
							s.setTrayNumber(basicTrayResult.getTrayNumber());
							basicTrayResult.setTrayState("OCCUPIED");
							ToolUtil.copyProperties(basicTrayResult, trayParam);
							basicTrayService.update(trayParam);
						} else {
							Tp.setTrayNumber(trayCode+TrayNumber);
							s.setTrayNumber(trayCode+TrayNumber);//托盘编号
							TrayNumber++;
							ToolUtil.copyProperties(Tp,bTray);
							tList.add(bTray);
							bTray = new BasicTray();
						}
						BigDecimal detailedPutnum2	=  detailedPutnum.subtract(Supportvolume);
						detailedPutnum = detailedPutnum2;
					}
					ToolUtil.copyProperties(s,putSingle);
					sList.add(putSingle);
					putSingle = new StoragePutSingle();
					s = new StoragePutSingleParam();
				}
				if (sList.size()>0) {
					//批量保存入库单名 ，托盘
                    this.saveBatchList(sList);
                    if (tList.size()>0) {
                    	basicTrayService.saveBatchList(tList);
                    }
					for (int i = 0; i < sList.size(); i++) {
						for (int j = 0; j < totallist.size(); j++) {
							if (sList.get(i).getPositionNumber().equals(totallist.get(j).getPositionNumber())) {
								BigDecimal putNum = new BigDecimal(1);
								BigDecimal traySize = new BigDecimal(totallist.get(j).getTraySize());
								traySize = traySize.subtract(putNum);
								BasicPositionParam param = totallist.get(j);
								param.setTraySize(traySize.toString());
								totallist.set(j, param);
							}
						}
					}
				}
			}
		}
		//更新入库单
		OrderPutParam orderPutParam = new OrderPutParam();
		orderPutParam.setId(orderPut.getId());
		orderPutParam.setSubmissionTime(new Date());//提交时间
		orderPutParam.setSubmissionUser(user.getUserId());//提交user
		orderPutParam.setSubmissionName(user.getName());//提交人名称
		orderPutParam.setBillstate("PENDING_INBOUND");
		orderPutService.update(orderPutParam);
		
		OrderPutParam param = new OrderPutParam();
        ToolUtil.copyProperties(orderPut,param);
		//生成货运单
		if ("On-Site Pickup".equals(orderPut.getPutMode())) {
	        if(c != null && ToolUtil.isNotEmpty(c.getWmsAddtms())&&c.getWmsAddtms().equals("1")) {
	        	orderTransportService.updateTransport(param);
	        	OrderTransportParam orderTransportParam = new OrderTransportParam();
	        	orderTransportParam.setCustomerOrder(param.getPutCustomerNumber());
	        	OrderTransportResult orderTransportResult = orderTransportService.findBySpec(orderTransportParam,null);
	        	if(orderTransportResult != null) {
	        		orderTransportService.auditorder(orderTransportResult.getId());
	        	}
	        }
		}
		return ResponseData.success();
	}

	/**
	 * 匹配可以装满的空库位
	 */
	private void packfulls(List<OrderPutDetailedResult> putDlist,List<OrderPutDetailedResult> totalputDlist, Long warehouseId,
			List<BasicPositionParam> totallist, List<StoragePutSingle> usableList,User user) {
		for (OrderPutDetailedResult putD:totalputDlist) {
			//匹配可以装满的空库位    规则
			//1, 用物料编码匹配   库位容量小于等于入库托数的空库位，如果没有再用物料大类匹配库区下   库位容量小于等于入库托数的空库位，没有的话不做推荐
			//2, 如果库中有相同批次的并且距离比空库位近的优先
			String bigtype = putD.getGoodsNumber().substring(0, 3);//截取前三位 物料大类码
			String goodsnumber = putD.getGoodsNumber();//商品编号
			Long deliverId = user.getDeliverId();
			Long deptId = user.getDeptId();
			Long goodsId = putD.getDetailedGoodsnum();
			//1,1 库位容量小于等于入库托数的空库位
			//1,2 和有同样商品相邻的库位优先，库位容量多的优先
			BasicPositionParam basicPositionParam = new BasicPositionParam();
			basicPositionParam.setDeliverId(deliverId);
			float f = Float.parseFloat(putD.getDetailedPutnum());
			int w = (int)(f+0.5);
			for (int i = 0; i < w; i++) {
				boolean a = loop(putDlist,bigtype,goodsnumber,basicPositionParam,deptId,warehouseId,goodsId,usableList,putD,totallist,user);
				float f2 = Float.parseFloat(putD.getDetailedPutnum());
				int w2 = (int)(f2+0.5);
				if (!a||w2<=0) {
					break;
				}
			}
		}
	}

	private boolean loop(List<OrderPutDetailedResult> putDlist,String bigtype,String goodsnumber, BasicPositionParam basicPositionParam, Long deptId, Long warehouseId,
			Long goodsId, List<StoragePutSingle> usableList, OrderPutDetailedResult putD,
			List<BasicPositionParam> totallist,User user) {
		//商品已存在 库位id
		Integer pid = null;
		Long deliverId = user.getDeliverId();
		for (int i = 0; i < usableList.size(); i++) {
			if (usableList.get(i).getGoodsId().longValue()==putD.getDetailedGoodsnum().longValue()) {
				BasicPositionParam param = new BasicPositionParam();
				param.setPositionNumber(usableList.get(i).getPositionNumber());
				param.setDeliverId(deliverId);
				pid = basicPositionService.findBySpec(param,deptId,user.getOperateId()).getId();
				break;
			}
		}
		if (pid==null) {
			StorageStockParam param = new StorageStockParam();
			param.setGoodsId(putD.getDetailedGoodsnum().longValue());
			param.setStockstate("put");
			param.setWarehouseId(warehouseId);
			StorageStockResult storageStock = storageStockService.findBySpec(param);
			if (storageStock!=null) {
				if(storageStock.getPositionId()!=null) {
					pid = Integer.parseInt(storageStock.getPositionId().toString());
				}
			}
		}
		if (pid==null) {
			StoragePutSingleParam param = new StoragePutSingleParam();
			param.setGoodsId(putD.getDetailedGoodsnum().longValue());
			param.setSingleState("NOT_STARTED");
			StoragePutSingleResult result = storagePutSingleService.findBywarehouseIdSpec(param,warehouseId);
			if (result!=null) {
				if(ToolUtil.isNotEmpty(result.getPositionNumber())){
					BasicPositionParam param2 = new BasicPositionParam();
					param2.setPositionNumber(result.getPositionNumber());
					param2.setDeliverId(deliverId);
					pid = basicPositionService.findBySpec(param2,deptId,user.getOperateId()).getId();
				}
			}
		}
		basicPositionParam.setId(pid);
		
		int flag = 1;//物料匹配标记
		boolean a = true;
		
		//计算入库托数  =  入库数量/每托存量/商品叠层
		BasicGoods basicGoods = basicGoodsService.getById(putD.getDetailedGoodsnum().longValue());
		BigDecimal goodsTraylayer = new BigDecimal(1);//商品叠层
		BigDecimal goodsSupportvolume = new BigDecimal(basicGoods.getGoodsSupportvolume());//每托存量
		if (ToolUtil.isNotEmpty(basicGoods.getGoodsTraylayer()!=null)) {
			goodsTraylayer = new BigDecimal(basicGoods.getGoodsTraylayer());
		}
		BigDecimal detailedPutnum = new BigDecimal(putD.getDetailedPutnum());//入库数量
		BigDecimal putSupportnum = detailedPutnum.divide(goodsSupportvolume,0,BigDecimal.ROUND_UP).divide(goodsTraylayer,0,BigDecimal.ROUND_UP);//入库托数(有小数直接进位，保留整数)
		
		List<BasicPositionResult> list = new ArrayList<BasicPositionResult>();
		list = basicPositionService.findEmptyList(null,goodsnumber,basicPositionParam,deptId,warehouseId,putSupportnum.toString(),user.getOperateId());//物料匹配库位
		if (list.size()==0) {
			flag = 2;
			list = basicPositionService.findEmptyList(bigtype,null,basicPositionParam,deptId,warehouseId,putSupportnum.toString(),user.getOperateId());//物料大类匹配库区下的库位
			if (list.size()==0) {
				a = false;
			}
		}
		if (list.size()>0) {
			//判断是否有同批次
			a = matching(putDlist,list,usableList,putD,totallist,warehouseId,basicGoods,user);
		}
		if (!a&&flag==1) {
			list = basicPositionService.findEmptyList(bigtype,null,basicPositionParam,deptId,warehouseId,putSupportnum.toString(),user.getOperateId());//物料大类匹配库区下的库位
			//判断是否有同批次
			a = matching(putDlist,list,usableList,putD,totallist,warehouseId,basicGoods,user);
		}
		return a;
	}

	//判断是否有同批次  比空库近的
	private boolean matching(List<OrderPutDetailedResult> putDlist,List<BasicPositionResult> list, List<StoragePutSingle> usableList, OrderPutDetailedResult putD,
			List<BasicPositionParam> totallist,Long warehouseId,BasicGoods basicGoods,User user) {
		boolean a = false;
		for (BasicPositionResult r : list) {
			boolean repeatflag = false;
			for (BasicPositionParam param : totallist) {
				if (r.getId().intValue()==param.getId().intValue()) {
					repeatflag = true;
					break;
				}
			}
			if (repeatflag) {
				continue;
			}
			
			BigDecimal goodsTraylayer = new BigDecimal(1);//商品叠层
			BigDecimal traySize = new BigDecimal(10);//库位托存量
			BigDecimal goodsSupportvolume = new BigDecimal(basicGoods.getGoodsSupportvolume());//每托存量
			if (basicGoods.getGoodsTraylayer()!=null) {
				goodsTraylayer = new BigDecimal(basicGoods.getGoodsTraylayer());
			}
			if (r.getTraySize()!=null) {
				traySize = new BigDecimal(r.getTraySize());
			}
			BigDecimal capacity = goodsTraylayer.multiply(traySize).multiply(goodsSupportvolume);//库位容量
			BigDecimal detailedPutnum = new BigDecimal(putD.getDetailedPutnum());//入库数量
			a = true;
			//库中有相同批次的，距离比空库位近  优先
			for (OrderPutDetailedResult p : putDlist) {
				if (p.getDetailedGoodsnum().longValue()==putD.getDetailedGoodsnum().longValue()) {
					boolean batchflag = preparebatch(p,warehouseId,r,totallist,user);
					if (batchflag) {
						return false;
					}
				}
			}
			
			putD.setDetailedPutnum(detailedPutnum.subtract(capacity).toString());
			
			StoragePutSingle putSingle = new StoragePutSingle();
			putSingle.setPositionNumber(r.getPositionNumber());//可以装满的空库位，推荐成功！
			putSingle.setGoodsId(putD.getDetailedGoodsnum().longValue());
			putSingle.setPutNum(goodsTraylayer.multiply(traySize).toString());
			usableList.add(putSingle);
			
			BasicPositionParam param3 = new BasicPositionParam();
			param3.setId(r.getId());
			param3.setDeliverId(putD.getDetailedGoodsnum().longValue());
			param3.setPositionNumber(r.getPositionNumber());
			param3.setTraySize(goodsTraylayer.multiply(traySize).toString());
			totallist.add(param3);
			break;
		}
		return a;
	}
	
	/**
	 * 匹配库中相同批次的  距离比空库位近的
	 * @param
	 * @param warehouseId
	 * @return
	 */
	private boolean preparebatch(OrderPutDetailedResult putD, Long warehouseId,BasicPositionResult r,List<BasicPositionParam> totallist,User user) {
		StoragePutSingleParam s = new StoragePutSingleParam();
		String bigtype = putD.getGoodsNumber().substring(0, 3);//截取前三位 物料大类码
		String goodsnumber = putD.getGoodsNumber();//商品编号
		Long deliverId = user.getDeliverId();
		Long deptId = user.getDeptId();
		Long goodsId = putD.getDetailedGoodsnum();
		String recommend = putD.getRecommend();
		//1, 用物料编码匹配库位，如果没有再用物料大类匹配库区下的库位，没有的话不做推荐
		//2, 有同品同批库位 (1. 入库单明细中 状态为未开始的2. 库存表中状态为在库，未入)
		BasicPositionParam basicPositionParam = new BasicPositionParam();
		basicPositionParam.setDeliverId(deliverId); 
		int flag = 1;//物料匹配标记
		List<BasicPositionResult> list = new ArrayList<BasicPositionResult>();
		list = basicPositionService.findListByIdentical(null,goodsnumber,basicPositionParam,deptId,warehouseId,goodsId,recommend,user.getOperateId());//物料匹配库位
		if (list.size()==0) {
			flag = 2;
			list = basicPositionService.findListByIdentical(bigtype,null,basicPositionParam,deptId,warehouseId,goodsId,recommend,user.getOperateId());//物料大类匹配库区下的库位
			if (list.size()==0) {
				return false;
			}
		}
		if (list.size()>0) {
			//进入第3.4.5条规则   (匹配相同批次的)
			identical(list,s,putD,totallist,r);
		}
		if (s.getPositionNumber()==null&&flag==1) {
			list = basicPositionService.findListByIdentical(bigtype,null,basicPositionParam,deptId,warehouseId,goodsId,recommend,user.getOperateId());//物料大类匹配库区下的库位
			//进入第3.4.5条规则   (匹配相同批次的)
			identical(list,s,putD,totallist,r);
		}
		if (s.getPositionNumber()!=null) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 匹配相同批次的
	 */
	private void identical(List<BasicPositionResult> list, StoragePutSingleParam s, OrderPutDetailedResult putD,List<BasicPositionParam> totallist
			,BasicPositionResult r2) {
		for (BasicPositionResult r : list) {
			int already = 0;//库位已推托数
			for (BasicPositionParam param : totallist) {
				if (r.getId().intValue()==param.getId().intValue()) {
					BigDecimal as = new BigDecimal(0);
					BigDecimal ts = new BigDecimal(param.getTraySize());
					if (ts.compareTo(as)==1) {
						already = Integer.parseInt(param.getTraySize());
					} 
				}
			}
			//3 判断  库位是否存在两种商品
			//1. 入库单明细中 状态为未开始的
			//2. 库存表中状态为在库，未入
			StorageStockParam param = new StorageStockParam();
			StoragePutSingleParam param2 = new StoragePutSingleParam();
			param.setPositionId(Long.parseLong(r.getId().toString()));
			param2.setPositionNumber(r.getPositionNumber());
			List<StorageStockResult> repeatList = storageStockService.checkPositionGoodsNum(param);//库存
			List<StoragePutSingleResult> repeatList2 = storagePutSingleService.checkPositionGoodsNum(param2);//入库单明细
			List<StorageStockResult> bergeList = berge(repeatList,repeatList2);//合并去重
			if (bergeList.size()<2) {
				//判断是否是空库位 已存在+本次已推
				if ((bergeList.size()+already)<1) {
					continue;
				} else {
					//4, 判断入库商品是否和库位商品一致
					if (bergeList.size()==0||putD.getDetailedGoodsnum().longValue()==bergeList.get(0).getGoodsId().longValue()) {
						//5, 判断是否满库：用商品叠层*库位托存量-库位库存托量>=1的可以推荐
						BasicGoods basicGoods = basicGoodsService.getById(putD.getDetailedGoodsnum().longValue());
						BigDecimal goodsTraylayer = new BigDecimal(1);//商品叠层
						BigDecimal traySize = new BigDecimal(10);//库位托存量
						if (basicGoods.getGoodsTraylayer()!=null) {
							goodsTraylayer = new BigDecimal(basicGoods.getGoodsTraylayer());
						}
						if (r.getTraySize()!=null) {
							traySize = new BigDecimal(r.getTraySize());
						}
						BigDecimal capacity = goodsTraylayer.multiply(traySize);//库位容量
						//查询库位库存托量
						//1. 入库单明细中 状态为未开始的2. 库存表中状态为在库，未入
						param.setGoodsId(putD.getDetailedGoodsnum());
						param2.setGoodsId(putD.getDetailedGoodsnum());
						int snum = storageStockService.findTrayListRecommend(param);
						int pnum = storagePutSingleService.findTrayListRecommend(param2);
						BigDecimal stocknum = new BigDecimal(snum+pnum+already);//库位当前库存托量+库位已推托数
						BigDecimal subBigDecimal = capacity.subtract(stocknum);//库位容量  - (库位当前库存托量+库位已推托数)
						BigDecimal as = new BigDecimal(1);
						if (subBigDecimal.compareTo(as)==1||subBigDecimal.compareTo(as)==0) {
							//判断批次相同
							if (bergeList.get(0).getProducetime().equals(putD.getDetailedDateofmanufacture())) {
								//未满库，批次相同！
								//判断空库位和相同批次库位  距离
								int empty = Integer.parseInt(r2.getPositionNumber().replaceAll("[a-zA-Z]",""));
								int equal = Integer.parseInt(r.getPositionNumber().replaceAll("[a-zA-Z]",""));
								if (equal<empty) {
									s.setPositionNumber(r.getPositionNumber());
									break;
								}
							}
						}
					}
				}
			}
		}
	}
	
	public static void main(String[] args) {
		String a = "A101";
		//System.out.println(Integer.parseInt(a.replaceAll("[a-zA-Z]","")));
	}

	/**
	 * 1 推荐库位
	 * 2 生成入库单明细
	 * @param
	 * @return StoragePutSingleParam
	 */
	private void prepare(StoragePutSingleParam s,OrderPutDetailedResult putD,Long warehouseId,List<BasicPositionParam> totallist,boolean packfull
			,boolean recommend,User user,BasicGoods bG) {
		//入库推荐库位    规则
		//1, 用物料编码匹配库位，如果没有再用物料大类匹配库区下的库位，没有的话不做推荐
		//2, 匹配可以装满的空库位,如果库中有相同批次的并且距离比空库位近的优先，然后有相同货物和相同批次的优先，然后按货物数量多的优先
		//3, 判断库位是否存在两种商品，存在的不做推荐
		//4, 判断入库商品是否和库位商品一致，不一致不做推荐
		//5, 判断是否满库：用商品叠层*库位托存量-库位库存托量>=1的可以推荐
		if (!packfull) {
			if (recommend) {
				//商品已存在 库位id
				Integer pid = null;
				Long deliverId = user.getDeliverId();
				Long deptId = user.getDeptId();
				for (int i = 0; i < totallist.size(); i++) {
					if (totallist.get(i).getDeliverId().longValue()==putD.getDetailedGoodsnum().longValue()) {
						BasicPositionParam param = new BasicPositionParam();
						param.setPositionNumber(totallist.get(i).getPositionNumber());
						param.setDeliverId(deliverId);
						pid = basicPositionService.findBySpec(param,deptId,user.getOperateId() ).getId();
						break;
					}
				}
				if (pid==null) {
					StorageStockParam param = new StorageStockParam();
					param.setGoodsId(putD.getDetailedGoodsnum().longValue());
					param.setStockstate("put");
					param.setWarehouseId(warehouseId);
					StorageStockResult storageStock = storageStockService.findBySpec(param);
					if (storageStock!=null) {
						if(storageStock.getPositionId()!=null) {
							pid = Integer.parseInt(storageStock.getPositionId().toString());
						}
					}
				}
				if (pid==null) {
					StoragePutSingleParam param = new StoragePutSingleParam();
					param.setGoodsId(putD.getDetailedGoodsnum().longValue());
					param.setSingleState("NOT_STARTED");
					StoragePutSingleResult result = storagePutSingleService.findBywarehouseIdSpec(param,warehouseId);
					if (result!=null) {
						BasicPositionParam param2 = new BasicPositionParam();
						param2.setPositionNumber(result.getPositionNumber());
						param2.setDeliverId(deliverId);
						pid = basicPositionService.findBySpec(param2,deptId,user.getOperateId()).getId();
					}
				}
				
				String bigtype = putD.getGoodsNumber().substring(0, 3);//截取前三位 物料大类码
				String goodsnumber = putD.getGoodsNumber();//商品编号
				Long goodsId = putD.getDetailedGoodsnum();
				String detailedDateofmanufacture = putD.getRecommend();
				//1, 用物料编码匹配库位，如果没有再用物料大类匹配库区下的库位，没有的话不做推荐
				//2, 有相同货物和相同批次的优先，然后按货物数量多的优先(1. 入库单明细中 状态为未开始的2. 库存表中状态为在库，未入)
				BasicPositionParam basicPositionParam = new BasicPositionParam();
				basicPositionParam.setDeliverId(deliverId); 
				basicPositionParam.setId(pid);
				int flag = 1;//物料匹配标记
				List<BasicPositionResult> list = new ArrayList<BasicPositionResult>();
				list = basicPositionService.findListByMaterial(null,goodsnumber,basicPositionParam,deptId,warehouseId,goodsId,detailedDateofmanufacture,user.getOperateId());//物料匹配库位
				if (list.size()==0) {
					flag = 2;
					list = basicPositionService.findListByMaterial(bigtype,null,basicPositionParam,deptId,warehouseId,goodsId,detailedDateofmanufacture,user.getOperateId());//物料大类匹配库区下的库位
				}
				if (list.size()>0) {
					//进入第3.4.5条规则
					rules(list,s,putD,totallist);
				}
				if (s.getPositionNumber()==null&&flag==1) {
					list = basicPositionService.findListByMaterial(bigtype,null,basicPositionParam,deptId,warehouseId,goodsId,detailedDateofmanufacture,user.getOperateId());//物料大类匹配库区下的库位
					//进入第3.4.5条规则
					rules(list,s,putD,totallist);
				}
			}
		}
		
		//入库单明细 基础信息
		s.setGoodsname(putD.getDetailedGoodsname());//商品名称
		s.setGoodsId(putD.getDetailedGoodsnum());//商品id
		s.setGoodsNumber(putD.getGoodsNumber());//商品编号
		s.setGoodsNo(putD.getGoodsNo());
		
		s.setFactory(putD.getDetailedFactory());//工厂号
		
		s.setGoodsWeight(bG.getGoodsWeight());//重量
		s.setGoodsVolume(bG.getGoodsVolume());//体积
		s.setUnitprice(bG.getGoodsCharging());//单价
		s.setSingleBatchnumber(putD.getDetailedBatchnumber());//批号
		s.setSingleDateofmanufacture(putD.getDetailedDateofmanufacture());//生产日期
		s.setRecommend(putD.getRecommend());//推荐批次
		
		s.setSingleRebubbles(putD.getDetailedRebubbles());//重泡货
		s.setSingleLargeclass(putD.getDetailedLargeclass());//大类
		s.setSingleGoodstype(putD.getDetailedGoodstype());//类别
		
		s.setGoodsUnit(putD.getGoodsUnit());
		s.setSinglePacking(putD.getDetailedPacking());//包装
		s.setGoodsSpecs(putD.getGoodsSpecs());
		s.setSingleState("NOT_RECEIVED");//入库单明细状态
	}
	
	//入库规则3.4.5
	private void rules(List<BasicPositionResult> list, StoragePutSingleParam s,OrderPutDetailedResult putD,List<BasicPositionParam> totallist) {
		for (BasicPositionResult r : list) {
			int already = 0;//库位已推托数
			for (BasicPositionParam param : totallist) {
				if (r.getId().intValue()==param.getId().intValue()) {
					BigDecimal as = new BigDecimal(0);
					BigDecimal ts = new BigDecimal(param.getTraySize());
					if (ts.compareTo(as)==1) {
						already = Integer.parseInt(param.getTraySize());
					} 
				}
			}
			//3 判断  库位是否存在两种商品
			//1. 入库单明细中 状态为未开始的
			//2. 库存表中状态为在库，未入
			StorageStockParam param = new StorageStockParam();
			StoragePutSingleParam param2 = new StoragePutSingleParam();
			param.setPositionId(Long.parseLong(r.getId().toString()));
			param2.setPositionNumber(r.getPositionNumber());
			List<StorageStockResult> repeatList = storageStockService.checkPositionGoodsNum(param);//库存
			List<StoragePutSingleResult> repeatList2 = storagePutSingleService.checkPositionGoodsNum(param2);//入库单明细
			List<StorageStockResult> bergeList = berge(repeatList,repeatList2);//合并去重
			if (bergeList.size()<2) {
				//判断是否是空库位 已存在+本次已推
				if ((bergeList.size()+already)<1) {
					s.setPositionNumber(r.getPositionNumber());//空库位，推荐成功！
					already++;
					boolean flag = false;
					for (int i = 0; i < totallist.size(); i++) {
						if (r.getId().intValue()==totallist.get(i).getId().intValue()) {
							BasicPositionParam param3 = totallist.get(i);
							param3.setTraySize(already+"");
							totallist.set(i, param3);
							flag = true;
						}
					}
					if (!flag) {
						BasicPositionParam param3 = new BasicPositionParam();
						param3.setId(r.getId());
						param3.setDeliverId(putD.getDetailedGoodsnum().longValue());
						param3.setPositionNumber(r.getPositionNumber());
						param3.setTraySize(already+"");
						totallist.add(param3);
					} 
					break;
				} else {
					//4, 判断入库商品是否和库位商品一致
					if (bergeList.size()==0||putD.getDetailedGoodsnum().longValue()==bergeList.get(0).getGoodsId().longValue()) {
						//5, 判断是否满库：用商品叠层*库位托存量-库位库存托量>=1的可以推荐
						BasicGoods basicGoods = basicGoodsService.getById(putD.getDetailedGoodsnum().longValue());
						BigDecimal goodsTraylayer = new BigDecimal(1);//商品叠层
						BigDecimal traySize = new BigDecimal(10);//库位托存量
						if (basicGoods.getGoodsTraylayer()!=null) {
							goodsTraylayer = new BigDecimal(basicGoods.getGoodsTraylayer());
						}
						if (r.getTraySize()!=null) {
							traySize = new BigDecimal(r.getTraySize());
						}
						BigDecimal capacity = goodsTraylayer.multiply(traySize);//库位容量
						//查询库位库存托量
						//1. 入库单明细中 状态为未开始的2. 库存表中状态为在库，未入
						param.setGoodsId(putD.getDetailedGoodsnum());
						param2.setGoodsId(putD.getDetailedGoodsnum());
						int snum = storageStockService.findTrayListRecommend(param);
						int pnum = storagePutSingleService.findTrayListRecommend(param2);
						BigDecimal stocknum = new BigDecimal(snum+pnum+already);//库位当前库存托量+库位已推托数
						BigDecimal subBigDecimal = capacity.subtract(stocknum);//库位容量  - (库位当前库存托量+库位已推托数)
						BigDecimal as = new BigDecimal(1);
						if (subBigDecimal.compareTo(as)==1||subBigDecimal.compareTo(as)==0) {
							s.setPositionNumber(r.getPositionNumber());//未满库，推荐成功！
							already++;
							boolean flag = false;
							for (int i = 0; i < totallist.size(); i++) {
								if (r.getId().intValue()==totallist.get(i).getId().intValue()) {
									BasicPositionParam param3 = totallist.get(i);
									param3.setTraySize(already+"");
									totallist.set(i, param3);
									flag = true;
								}
							}
							if (!flag) {
								BasicPositionParam param3 = new BasicPositionParam();
								param3.setId(r.getId());
								param3.setDeliverId(putD.getDetailedGoodsnum().longValue());
								param3.setPositionNumber(r.getPositionNumber());
								param3.setTraySize(already+"");
								totallist.add(param3);
							} 
							break;
						}
					}
				}
			}
		}
	}

	//合并list
	private static List<StorageStockResult> berge(List<StorageStockResult> repeatList,List<StoragePutSingleResult> repeatList2) {
		List<StorageStockResult> newList = new ArrayList<StorageStockResult>();
		for  ( int  i  =   0 ; i  <  repeatList.size()  -   1 ; i ++ )  {       
		      for  ( int  j  =  repeatList.size()  -   1 ; j  >  i; j -- )  {       
		           if  (repeatList.get(j).equals(repeatList.get(i)))  {       
		        	   repeatList.remove(j);       
		            }        
		      }        
		}  
		for  ( int  i  =   0 ; i  <  repeatList2.size()  -   1 ; i ++ )  {       
		      for  ( int  j  =  repeatList2.size()  -   1 ; j  >  i; j -- )  {       
		           if  (repeatList2.get(j).equals(repeatList2.get(i)))  {       
		        	   repeatList2.remove(j);       
		            }        
		      }        
		}  
		for (int i = 0; i < repeatList2.size(); i++) {
			StorageStockResult r = new StorageStockResult();
			r.setGoodsId(repeatList2.get(i).getGoodsId());
			r.setProducetime(repeatList2.get(i).getSingleDateofmanufacture());
			newList.add(r);
		}
		newList.removeAll(repeatList);  
		newList.addAll(repeatList);  
		for (int i = 0; i < newList.size(); i++) {
			if (newList.get(i).getGoodsId()==null) {
				newList.remove(i);
			}
		}
		return newList;
	}

	@Override
	public StoragePutSingle findByThelastone() {
		return this.baseMapper.findByThelastone();
	}

	@Override
	public boolean saveBatchList(List<StoragePutSingle> list) {
		return this.baseMapper.saveBatchList(list);
	}

	@Override
	public LayuiPageInfo findPageDISTINCTbatch(StoragePutSingleParam storagePutSingleParam) {
		Page pageContext = getPageContext();
		IPage page = this.baseMapper.findPageDISTINCTbatch(pageContext, storagePutSingleParam);
		return LayuiPageFactory.createPageInfo(page);
	}

	@Override
	public List<StoragePutSingleResult> finByOnlyOne(StoragePutSingleParam sp) {
		return this.baseMapper.finByOnlyOne(sp);
	}

	@Override
	public boolean updateBatchList(List<StoragePutSingle> splist) {
		return this.baseMapper.updateBatchList(splist);
	}

	@Override
	public boolean batchDelete(List<Integer> pList) {
		return this.baseMapper.batchDelete(pList);
	}

	@Override
	public StoragePutSingleResult findBySpecL1(StoragePutSingleParam storagePutSingleParam) {
		return this.baseMapper.findBySpecL1(storagePutSingleParam);
	}

	@Override
	public boolean updateBatchListState(List<StoragePutSingle> list) {
		return this.baseMapper.updateBatchListState(list);
	}

	@Override
	public List<StoragePutSingleResult> findpositionlist(StoragePutSingleParam storagePutSingleParam) {
		return this.baseMapper.findpositionlist(storagePutSingleParam);
	}

	@Override
	public List<StoragePutSingleResult> confirmpositionGoodslist(StoragePutSingleParam storagePutSingleParam) {
		return this.baseMapper.confirmpositionGoodslist(storagePutSingleParam);
	}

	@Override
	public List<StoragePutSingleResult> checkPositionGoodsNum(StoragePutSingleParam param) {
		return this.baseMapper.checkPositionGoodsNum(param);
	}

	@Override
	public int findTrayListRecommend(StoragePutSingleParam param) {
		return this.baseMapper.findTrayListRecommend(param);
	}

	@Override
	public List<StoragePutSingleResult> totalListByGandPSpec(StoragePutSingleParam putDetailedParam) {
		return this.baseMapper.totalListByGandPSpec(putDetailedParam);
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class,timeout=2000)
	public void allotPositionNew(StoragePutSingleParam storagePutSingleParam,User user) {

		final Long deliverId = user.getDeliverId();
		final Long deptId = user.getDeptId();
		StoragePutSingleParam putDetailedParam = new StoragePutSingleParam();
		putDetailedParam.setStorageNumber(storagePutSingleParam.getStorageNumber());
		putDetailedParam.setGoodsId(storagePutSingleParam.getGoodsId());
		List<StoragePutSingleResult> putDlist = storagePutSingleService.totalListByGandPSpec(putDetailedParam);//入库单明细
		if (putDlist.size() != 0){
			StoragePutParam storagePutParam = new StoragePutParam();
			storagePutParam.setStorageNumber(storagePutSingleParam.getStorageNumber());
			StoragePutResult result = storagePutService.findSpec(storagePutParam);

			List<BasicPositionParam> totallist = new ArrayList<BasicPositionParam>();//合计推荐库位的托数量
			List<StoragePutSingle> usableList = new ArrayList<StoragePutSingle>();//库位  商品  数量(匹配空库位集合)

			//匹配可以装满的  空库位
			//匹配空库位  开关
			SysSwitchParam dParam = new SysSwitchParam();
			dParam.setCode("allot_location");
			dParam.setDeliverId(deliverId);
			dParam.setDeptId(deptId);
			SysSwitchResult dResult = sysSwitchService.findBySpec(dParam,user.getOperateId());
			if (dResult != null){
				if (ToolUtil.isNotEmpty(dResult.getOperation())) {
					if ("Y".equals(dResult.getOperation())) {
						List<StoragePutSingleResult> putlist = storagePutSingleService.referPosition(putDetailedParam);
						List<StoragePutSingleResult> totalputDlist = storagePutSingleService.totalListBySpec(putDetailedParam);//入库订单明细 合计商品
						packfulls2(putlist,totalputDlist,result.getWarehouseId(),totallist,usableList,user);
					}
				}
			}

			//入库推荐  开关
			dParam.setCode("alloutPostion");
			dParam.setDeliverId(deliverId);
			dParam.setDeptId(deptId);
			SysSwitchResult dResult2 = sysSwitchService.findBySpec(dParam,user.getOperateId());
			boolean recommend = false;
			if (dResult2 != null){
				if (ToolUtil.isNotEmpty(dResult2.getOperation())) {
					if ("Y".equals(dResult2.getOperation())) {
						recommend = true;
					}
				}
			}

			List<StoragePutSingleResult> newputDlist = new ArrayList<StoragePutSingleResult>();
			BigDecimal as = new BigDecimal(0);
			for (StoragePutSingleResult PutD : putDlist){

				boolean packfull = false;
				StoragePutSingle u = null;
				ListIterator<StoragePutSingle> li = usableList.listIterator();
				while (li.hasNext()) {
					u = li.next();
					if (u.getGoodsId().longValue()==PutD.getGoodsId().longValue()) {
						BigDecimal putNum = new BigDecimal(u.getPutNum());
						BigDecimal sub = new BigDecimal(1);
						if (putNum.compareTo(as)==1) {
							putNum = putNum.subtract(sub);
							u.setPutNum(putNum.toString());
							li.set(u);
							PutD.setPositionNumber(u.getPositionNumber());
							packfull = true;
							break;
						}
					}
				}
				if (!packfull) {
					prepare2(PutD,PutD,result.getWarehouseId(),totallist,packfull,recommend,user);//生成入库单明细，推荐库位
				}
				newputDlist.add(PutD);
			}

			//修改库位
			storagePutSingleService.updateBatchListPosition(newputDlist);
		}

	}

	@Override
	@Transactional(rollbackFor = Exception.class,timeout=2000)
	public void allotPosition(StoragePutSingleParam storagePutSingleParam,User user) {

		final Long deliverId = userService.getDeliverId();
		final Long deptId = userService.getDeptId();
		StoragePutSingleParam putDetailedParam = new StoragePutSingleParam();
		putDetailedParam.setStorageNumber(storagePutSingleParam.getStorageNumber());
		putDetailedParam.setGoodsId(storagePutSingleParam.getGoodsId());
		List<StoragePutSingleResult> putDlist = storagePutSingleService.totalListByGandPSpec(putDetailedParam);//入库单明细
		if (putDlist.size() != 0){
			StoragePutParam storagePutParam = new StoragePutParam();
			storagePutParam.setStorageNumber(storagePutSingleParam.getStorageNumber());
			StoragePutResult result = storagePutService.findSpec(storagePutParam);

			List<BasicPositionParam> totallist = new ArrayList<BasicPositionParam>();//合计推荐库位的托数量
			List<StoragePutSingle> usableList = new ArrayList<StoragePutSingle>();//库位  商品  数量(匹配空库位集合)

			//匹配可以装满的  空库位
			//匹配空库位  开关
			SysSwitchParam dParam = new SysSwitchParam();
			dParam.setCode("allot_location");
			dParam.setDeliverId(deliverId);
			dParam.setDeptId(deptId);
			SysSwitchResult dResult = sysSwitchService.findBySpec(dParam,user.getOperateId());
			if (dResult != null){
				if (ToolUtil.isNotEmpty(dResult.getOperation())) {
					if ("Y".equals(dResult.getOperation())) {
						List<StoragePutSingleResult> putlist = storagePutSingleService.referPosition(putDetailedParam);
						List<StoragePutSingleResult> totalputDlist = storagePutSingleService.totalListBySpec(putDetailedParam);//入库订单明细 合计商品
						packfulls2(putlist,totalputDlist,result.getWarehouseId(),totallist,usableList,user);
					}
				}
			}

			//入库推荐  开关
			dParam.setCode("alloutPostion");
			dParam.setDeliverId(deliverId);
			dParam.setDeptId(deptId);
			SysSwitchResult dResult2 = sysSwitchService.findBySpec(dParam,user.getOperateId());
			boolean recommend = false;
			if (dResult2 != null){
				if (ToolUtil.isNotEmpty(dResult2.getOperation())) {
					if ("Y".equals(dResult2.getOperation())) {
						recommend = true;
					}
				}
			}

			List<StoragePutSingleResult> newputDlist = new ArrayList<StoragePutSingleResult>();
			BigDecimal as = new BigDecimal(0);
			for (StoragePutSingleResult PutD : putDlist){

				boolean packfull = false;
				StoragePutSingle u = null;
				ListIterator<StoragePutSingle> li = usableList.listIterator();
				while (li.hasNext()) {
					u = li.next();
					if (u.getGoodsId().longValue()==PutD.getGoodsId().longValue()) {
						BigDecimal putNum = new BigDecimal(u.getPutNum());
						BigDecimal sub = new BigDecimal(1);
						if (putNum.compareTo(as)==1) {
							putNum = putNum.subtract(sub);
							u.setPutNum(putNum.toString());
							li.set(u);
							PutD.setPositionNumber(u.getPositionNumber());
							packfull = true;
							break;
						}
					}
				}
				if (!packfull) {
					prepare2(PutD,PutD,result.getWarehouseId(),totallist,packfull,recommend,user);//生成入库单明细，推荐库位
				}
				newputDlist.add(PutD);
			}

			//修改库位
			storagePutSingleService.updateBatchListPosition(newputDlist);
		}

	}

	@Override
	public List<StoragePutSingleResult> totalListBySpec(StoragePutSingleParam putDetailedParam) {
		return this.baseMapper.totalListBySpec(putDetailedParam);
	}

	@Override
	public void updateBatchListPosition(List<StoragePutSingleResult> list) {
		this.baseMapper.updateBatchListPosition(list);
	}

	@Override
	public List<StoragePutSingleResult> referPosition(StoragePutSingleParam putDetailedParam) {
		return this.baseMapper.referPosition(putDetailedParam);
	}

	private final void packfulls2(List<StoragePutSingleResult> putDlist,List<StoragePutSingleResult> totalputDlist, Long warehouseId,
						   List<BasicPositionParam> totallist, List<StoragePutSingle> usableList,User user) {
		for (StoragePutSingleResult putD:totalputDlist) {
			//匹配可以装满的空库位    规则
			//1, 用物料编码匹配   库位容量小于等于入库托数的空库位，如果没有再用物料大类匹配库区下   库位容量小于等于入库托数的空库位，没有的话不做推荐
			//2, 如果库中有相同批次的并且距离比空库位近的优先
			final String bigtype = putD.getGoodsNumber().substring(0, 3);//截取前三位 物料大类码
			final String goodsnumber = putD.getGoodsNumber();//商品编号
			final Long goodsId = putD.getGoodsId();
			//1,1 库位容量小于等于入库托数的空库位
			//1,2 和有同样商品相邻的库位优先，库位容量多的优先
			BasicPositionParam basicPositionParam = new BasicPositionParam();
			basicPositionParam.setDeliverId(user.getDeliverId() );
			loop2(putDlist,bigtype,goodsnumber,basicPositionParam,warehouseId,goodsId,usableList,putD,totallist,user);
			
//			final float f = Float.parseFloat(putD.getPutNum());
//			final int w = (int)(f+0.5);
//			for (int i = 0,length = w; i < length; i++) {
//				final boolean a = loop2(putDlist,bigtype,goodsnumber,basicPositionParam,deptId,warehouseId,goodsId,usableList,putD,totallist,deliverId);
//				final float f2 = Float.parseFloat(putD.getPutNum());
//				final int w2 = (int)(f2+0.5);
//				if (!a||w2<=0) {
//					break;
//				}
//			}
		}
	}

	private final boolean loop2(List<StoragePutSingleResult> putDlist,String bigtype,String goodsnumber, BasicPositionParam basicPositionParam, Long warehouseId,
						 Long goodsId, List<StoragePutSingle> usableList, StoragePutSingleResult putD,
						 List<BasicPositionParam> totallist,User user) {
		//商品已存在 库位id
		Integer pid = null;
//		for (StoragePutSingle u : usableList) {
//			if (u.getGoodsId().longValue()==putD.getGoodsId().longValue()) {
//				BasicPositionParam param = new BasicPositionParam();
//				param.setPositionNumber(u.getPositionNumber());
//				param.setDeliverId(deliverId);
//				pid = basicPositionService.findBySpec(param,deptId).getId();
//				break;
//			}
//		}
		if (pid==null) {
			StorageStockParam param = new StorageStockParam();
			param.setGoodsId(putD.getGoodsId().longValue());
			param.setStockstate("put");
			param.setWarehouseId(warehouseId);
			StorageStockResult storageStock = storageStockService.findBySpec(param);
			if (storageStock!=null) {
				if(storageStock.getPositionId()!=null) {
					pid = Integer.parseInt(storageStock.getPositionId().toString());
				}
			}
		}
		if (pid==null) {
			StoragePutSingleParam param = new StoragePutSingleParam();
			param.setGoodsId(putD.getGoodsId().longValue());
			param.setSingleState("NOT_STARTED");
			StoragePutSingleResult result = storagePutSingleService.findBywarehouseIdSpec(param, warehouseId);
			if (result!=null) {
			    if (ToolUtil.isNotEmpty(result.getPositionNumber())){
                    BasicPositionParam param2 = new BasicPositionParam();
                    param2.setPositionNumber(result.getPositionNumber());
                    param2.setDeliverId(user.getDeliverId() );
                    pid = basicPositionService.findBySpec(param2,user.getDeptId(),user.getOperateId()).getId();
                }
			}
		}
		basicPositionParam.setId(pid);

		int flag = 1;//物料匹配标记
		boolean a = true;

		//计算入库托数  =  入库数量/每托存量/商品叠层
		BasicGoods basicGoods = basicGoodsService.getById(putD.getGoodsId().longValue());
		BigDecimal goodsTraylayer = new BigDecimal(1);//商品叠层
		final BigDecimal goodsSupportvolume = new BigDecimal(basicGoods.getGoodsSupportvolume());//每托存量
		if (ToolUtil.isNotEmpty(basicGoods.getGoodsTraylayer()!=null)) {
			goodsTraylayer = new BigDecimal(basicGoods.getGoodsTraylayer());
		}
		final BigDecimal detailedPutnum = new BigDecimal(putD.getPutNum());//入库数量
		final BigDecimal putSupportnum = detailedPutnum.divide(goodsSupportvolume,0,BigDecimal.ROUND_UP).divide(goodsTraylayer,0,BigDecimal.ROUND_UP);//入库托数(有小数直接进位，保留整数)

		List<BasicPositionResult> list = new ArrayList<BasicPositionResult>();
		list = basicPositionService.findEmptyList(null,goodsnumber,basicPositionParam,user.getDeptId(),warehouseId,putSupportnum.toString(),user.getOperateId());//物料匹配库位
		if (list.size()==0) {
			flag = 2;
                list = basicPositionService.findEmptyList(bigtype,null,basicPositionParam,user.getDeptId(),warehouseId,putSupportnum.toString(),user.getOperateId());//物料大类匹配库区下的库位
                if (list.size()==0) {
                    a = false;
			}
		}
		if (list.size()>0) {
			//判断是否有同批次
			a = matching2(putDlist,list,usableList,putD,totallist,warehouseId,basicGoods,user);
		}
		if (!a&&flag==1) {
			list = basicPositionService.findEmptyList(bigtype,null,basicPositionParam,user.getDeptId(),warehouseId,putSupportnum.toString(),user.getOperateId());//物料大类匹配库区下的库位
			//判断是否有同批次
			a = matching2(putDlist,list,usableList,putD,totallist,warehouseId,basicGoods,user);
		}
		return a;
	}

	//判断是否有同批次  比空库近的
	private final boolean matching2(List<StoragePutSingleResult> putDlist,List<BasicPositionResult> list, List<StoragePutSingle> usableList, StoragePutSingleResult putD,
							 List<BasicPositionParam> totallist,Long warehouseId,BasicGoods basicGoods,User user) {
		boolean a = false;
		boolean preparebatch = true;
		for (BasicPositionResult r : list) {
			boolean repeatflag = false;
			for (BasicPositionParam param : totallist) {
				if (r.getId().intValue()==param.getId().intValue()) {
					repeatflag = true;
					break;
				}
			}
			if (repeatflag) {
				continue;
			}

			BigDecimal goodsTraylayer = new BigDecimal(1);//商品叠层
			BigDecimal traySize = new BigDecimal(10);//库位托存量
			final BigDecimal goodsSupportvolume = new BigDecimal(basicGoods.getGoodsSupportvolume());//每托存量
			if (basicGoods.getGoodsTraylayer()!=null) {
				goodsTraylayer = new BigDecimal(basicGoods.getGoodsTraylayer());
			}
			if (r.getTraySize()!=null) {
				traySize = new BigDecimal(r.getTraySize());
			}
			final BigDecimal capacity = goodsTraylayer.multiply(traySize).multiply(goodsSupportvolume);//库位容量
			final BigDecimal detailedPutnum = new BigDecimal(putD.getPutNum());//入库数量
			
			//重新计算入库托数  =  入库数量/每托存量/商品叠层
			final BigDecimal putSupportnum = detailedPutnum.divide(goodsSupportvolume,0,BigDecimal.ROUND_UP).divide(goodsTraylayer,0,BigDecimal.ROUND_UP);//入库托数(有小数直接进位，保留整数)
			
			//判断是否还能装满空库位
			if (putSupportnum.compareTo(traySize) == -1) {
				return false;
			}
			
			a = true;
			if (preparebatch) {
				//库中有相同批次的，距离比空库位近  优先
				for (StoragePutSingleResult p : putDlist) {
					if (p.getGoodsId().longValue()==putD.getGoodsId().longValue()) {
						boolean batchflag = preparebatch2(p,warehouseId,r,totallist,user);
						if (batchflag) {
							return false;
						}
					}
				}
			}
			preparebatch = false;

			putD.setPutNum(detailedPutnum.subtract(capacity).toString());

			StoragePutSingle putSingle = new StoragePutSingle();
			putSingle.setPositionNumber(r.getPositionNumber());//可以装满的空库位，推荐成功！
			putSingle.setGoodsId(putD.getGoodsId().longValue());
			putSingle.setPutNum(goodsTraylayer.multiply(traySize).toString());
			usableList.add(putSingle);

			BasicPositionParam param3 = new BasicPositionParam();
			param3.setId(r.getId());
			param3.setDeliverId(putD.getGoodsId().longValue());
			param3.setPositionNumber(r.getPositionNumber());
			param3.setTraySize(goodsTraylayer.multiply(traySize).toString());
			totallist.add(param3);
		}
		return a;
	}

	/**
	 * 匹配库中相同批次的  距离比空库位近的
	 * @param warehouseId
	 * @return
	 */
	private final boolean preparebatch2(StoragePutSingleResult putD, Long warehouseId,BasicPositionResult r,List<BasicPositionParam> totallist
			,User user) {
		StoragePutSingleParam s = new StoragePutSingleParam();
		final String bigtype = putD.getGoodsNumber().substring(0, 3);//截取前三位 物料大类码
		final String goodsnumber = putD.getGoodsNumber();//商品编号
		final Long goodsId = putD.getGoodsId();
		final String recommend = putD.getRecommend();
		//1, 用物料编码匹配库位，如果没有再用物料大类匹配库区下的库位，没有的话不做推荐
		//2, 有同品同批库位 (1. 入库单明细中 状态为未开始的2. 库存表中状态为在库，未入)
		BasicPositionParam basicPositionParam = new BasicPositionParam();
		basicPositionParam.setDeliverId(user.getDeliverId());
		int flag = 1;//物料匹配标记
		List<BasicPositionResult> list = new ArrayList<BasicPositionResult>();
		list = basicPositionService.findListByIdentical(null,goodsnumber,basicPositionParam,user.getDeptId() ,warehouseId,goodsId,recommend,user.getOperateId());//物料匹配库位
		if (list.size()==0) {
			flag = 2;
			list = basicPositionService.findListByIdentical(bigtype,null,basicPositionParam,user.getDeptId(),warehouseId,goodsId,recommend,user.getOperateId());//物料大类匹配库区下的库位
			if (list.size()==0) {
				return false;
			}
		}
		if (list.size()>0) {
			//进入第3.4.5条规则   (匹配相同批次的)
			identical2(list,s,putD,totallist,r);
		}
		if (s.getPositionNumber()==null&&flag==1) {
			list = basicPositionService.findListByIdentical(bigtype,null,basicPositionParam,user.getDeptId(),warehouseId,goodsId,recommend,user.getOperateId());//物料大类匹配库区下的库位
			//进入第3.4.5条规则   (匹配相同批次的)
			identical2(list,s,putD,totallist,r);
		}
		if (s.getPositionNumber()!=null) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 匹配相同批次的
	 */
	private final void identical2(List<BasicPositionResult> list, StoragePutSingleParam s, StoragePutSingleResult putD,List<BasicPositionParam> totallist
			,BasicPositionResult r2) {
		for (BasicPositionResult r : list) {
			int already = 0;//库位已推托数
			for (BasicPositionParam param : totallist) {
				if (r.getId().intValue()==param.getId().intValue()) {
					final BigDecimal as = new BigDecimal(0);
					final BigDecimal ts = new BigDecimal(param.getTraySize());
					if (ts.compareTo(as)==1) {
						already = Integer.parseInt(param.getTraySize());
					}
					break;
				}
			}
			//3 判断  库位是否存在两种商品
			//1. 入库单明细中 状态为未开始的
			//2. 库存表中状态为在库，未入
			StorageStockParam param = new StorageStockParam();
			StoragePutSingleParam param2 = new StoragePutSingleParam();
			param.setPositionId(Long.parseLong(r.getId().toString()));
			param2.setPositionNumber(r.getPositionNumber());
			List<StorageStockResult> repeatList = storageStockService.checkPositionGoodsNum(param);//库存
			List<StoragePutSingleResult> repeatList2 = storagePutSingleService.checkPositionGoodsNum(param2);//入库单明细
			List<StorageStockResult> bergeList = berge2(repeatList,repeatList2);//合并去重
			if (bergeList.size()<2) {
				//判断是否是空库位 已存在+本次已推
				if ((bergeList.size()+already)<1) {
					continue;
				} else {
					//4, 判断入库商品是否和库位商品一致
					if (bergeList.size()==0||putD.getGoodsId().longValue()==bergeList.get(0).getGoodsId().longValue()) {
						//5, 判断是否满库：用商品叠层*库位托存量-库位库存托量>=1的可以推荐
						BasicGoods basicGoods = basicGoodsService.getById(putD.getGoodsId().longValue());
						BigDecimal goodsTraylayer = new BigDecimal(1);//商品叠层
						BigDecimal traySize = new BigDecimal(10);//库位托存量
						if (basicGoods.getGoodsTraylayer()!=null) {
							goodsTraylayer = new BigDecimal(basicGoods.getGoodsTraylayer());
						}
						if (r.getTraySize()!=null) {
							traySize = new BigDecimal(r.getTraySize());
						}
						final BigDecimal capacity = goodsTraylayer.multiply(traySize);//库位容量
						//查询库位库存托量
						//1. 入库单明细中 状态为未开始的2. 库存表中状态为在库，未入
						param.setGoodsId(putD.getGoodsId());
						param2.setGoodsId(putD.getGoodsId());
						final int snum = storageStockService.findTrayListRecommend(param);
						final int pnum = storagePutSingleService.findTrayListRecommend(param2);
						final BigDecimal stocknum = new BigDecimal(snum+pnum+already);//库位当前库存托量+库位已推托数
						final BigDecimal subBigDecimal = capacity.subtract(stocknum);//库位容量  - (库位当前库存托量+库位已推托数)
						final BigDecimal as = new BigDecimal(1);
						if (subBigDecimal.compareTo(as)==1||subBigDecimal.compareTo(as)==0) {
							//判断批次相同
							if (bergeList.get(0).getProducetime().equals(putD.getSingleDateofmanufacture())) {
								//未满库，批次相同！
								//判断空库位和相同批次库位  距离
								final int empty = Integer.parseInt(r2.getPositionNumber().replaceAll("[a-zA-Z]",""));
								final int equal = Integer.parseInt(r.getPositionNumber().replaceAll("[a-zA-Z]",""));
								if (equal<empty) {
									s.setPositionNumber(r.getPositionNumber());
									break;
								}
							}
						}
					}
				}
			}
		}
	}

	/**
	 * 1 推荐库位
	 * 2 生成入库单明细
	 * @param
	 * @return StoragePutSingleParam
	 */
	private final void prepare2(StoragePutSingleResult s,StoragePutSingleResult putD,Long warehouseId,List<BasicPositionParam> totallist,boolean packfull,boolean recommend
			,User user) {
		//入库推荐库位    规则
		//1, 用物料编码匹配库位，如果没有再用物料大类匹配库区下的库位，没有的话不做推荐
		//2, 匹配可以装满的空库位,如果库中有相同批次的并且距离比空库位近的优先，然后有相同货物和相同批次的优先，然后按货物数量多的优先
		//3, 判断库位是否存在两种商品，存在的不做推荐
		//4, 判断入库商品是否和库位商品一致，不一致不做推荐
		//5, 判断是否满库：用商品叠层*库位托存量-库位库存托量>=1的可以推荐
		if (!packfull) {
			if (recommend) {
				//商品已存在 库位id
				Integer pid = null;
				ListIterator<BasicPositionParam> totallistl = totallist.listIterator();
				BasicPositionParam o = null;
				while (totallistl.hasNext()) {
					o = totallistl.next();
					if (o.getDeliverId().longValue()==putD.getGoodsId().longValue()) {
						BasicPositionParam param = new BasicPositionParam();
						param.setPositionNumber(o.getPositionNumber());
						param.setDeliverId(user.getDeliverId() );
						pid = basicPositionService.findBySpec(param,user.getDeptId(),user.getOperateId()).getId();
						break;
					}
				}
				if (pid==null) {
					StorageStockParam param = new StorageStockParam();
					param.setGoodsId(putD.getGoodsId().longValue());
					param.setStockstate("put");
					StorageStockResult storageStock = storageStockService.findBySpec(param);
					if (storageStock!=null) {
						if(storageStock.getPositionId() != null) {
							pid = Integer.parseInt(storageStock.getPositionId().toString());
						}
					}
				}
				if (pid==null) {
					StoragePutSingleParam param = new StoragePutSingleParam();
					param.setGoodsId(putD.getGoodsId().longValue());
					param.setSingleState("NOT_STARTED");
					StoragePutSingleResult result = storagePutSingleService.findBySpec(param);
					if (result!=null) {
						if (ToolUtil.isNotEmpty(result.getPositionNumber())){
							BasicPositionParam param2 = new BasicPositionParam();
							param2.setPositionNumber(result.getPositionNumber());
							param2.setDeliverId(user.getDeliverId() );
							pid = basicPositionService.findBySpec(param2,user.getDeptId(),user.getOperateId()).getId();
						}
					}
				}

				final String bigtype = putD.getGoodsNumber().substring(0, 3);//截取前三位 物料大类码
				final String goodsnumber = putD.getGoodsNumber();//商品编号
				final Long goodsId = putD.getGoodsId();
				final String detailedDateofmanufacture = putD.getRecommend();
				//1, 用物料编码匹配库位，如果没有再用物料大类匹配库区下的库位，没有的话不做推荐
				//2, 有相同货物和相同批次的优先，然后按货物数量多的优先(1. 入库单明细中 状态为未开始的2. 库存表中状态为在库，未入)
				BasicPositionParam basicPositionParam = new BasicPositionParam();
				basicPositionParam.setDeliverId(user.getDeliverId());
				basicPositionParam.setId(pid);
				int flag = 1;//物料匹配标记
				List<BasicPositionResult> list = new ArrayList<BasicPositionResult>();
				list = basicPositionService.findListByMaterial(null,goodsnumber,basicPositionParam,user.getDeptId(),warehouseId,goodsId,detailedDateofmanufacture,user.getOperateId());//物料匹配库位
				if (list.size()==0) {
					flag = 2;
					list = basicPositionService.findListByMaterial(bigtype,null,basicPositionParam,user.getDeptId(),warehouseId,goodsId,detailedDateofmanufacture,user.getOperateId());//物料大类匹配库区下的库位
				}
				if (list.size()>0) {
					//进入第3.4.5条规则
					rules2(list,s,putD,totallist);
				}
				if (s.getPositionNumber()==null&&flag==1) {
					list = basicPositionService.findListByMaterial(bigtype,null,basicPositionParam,user.getDeptId(),warehouseId,goodsId,detailedDateofmanufacture,user.getOperateId());//物料大类匹配库区下的库位
					//进入第3.4.5条规则
					rules2(list,s,putD,totallist);
				}
			}
		}
	}

	//入库规则3.4.5
	private final void rules2(List<BasicPositionResult> list, StoragePutSingleResult s,StoragePutSingleResult putD,List<BasicPositionParam> totallist) {
		for (BasicPositionResult r : list) {
			int already = 0;//库位已推托数
			ListIterator<BasicPositionParam> totallistl = totallist.listIterator();
			BasicPositionParam paramp = null;
			while (totallistl.hasNext()) {
				paramp = totallistl.next();
				if (r.getId().intValue()==paramp.getId().intValue()) {
					final BigDecimal as = new BigDecimal(0);
					final BigDecimal ts = new BigDecimal(paramp.getTraySize());
					if (ts.compareTo(as)==1) {
						already = Integer.parseInt(paramp.getTraySize());
					}
					break;
				}
			}
			//3 判断  库位是否存在两种商品
			//1. 入库单明细中 状态为未开始的
			//2. 库存表中状态为在库，未入
			StorageStockParam param = new StorageStockParam();
			StoragePutSingleParam param2 = new StoragePutSingleParam();
			param.setPositionId(Long.parseLong(r.getId().toString()));
			param2.setPositionNumber(r.getPositionNumber());
			List<StorageStockResult> repeatList = storageStockService.checkPositionGoodsNum(param);//库存
			List<StoragePutSingleResult> repeatList2 = storagePutSingleService.checkPositionGoodsNum(param2);//入库单明细
			List<StorageStockResult> bergeList = berge2(repeatList,repeatList2);//合并去重
			if (bergeList.size()<2) {
				//判断是否是空库位 已存在+本次已推
				if ((bergeList.size()+already)<1) {
					s.setPositionNumber(r.getPositionNumber());//空库位，推荐成功！
					already++;
					boolean flag = false;
					totallistl = totallist.listIterator();
					while (totallistl.hasNext()) {
						paramp = totallistl.next();
						if (r.getId().intValue()==paramp.getId().intValue()) {
							paramp.setTraySize(already+"");
							totallistl.set(paramp);
							flag = true;
							break;
						}
					}
					if (!flag) {
						BasicPositionParam param3 = new BasicPositionParam();
						param3.setId(r.getId());
						param3.setDeliverId(putD.getGoodsId().longValue());
						param3.setPositionNumber(r.getPositionNumber());
						param3.setTraySize(already+"");
						totallistl.add(param3);
					}
					break;
				} else {
					//4, 判断入库商品是否和库位商品一致
					if (bergeList.size()==0||putD.getGoodsId().longValue()==bergeList.get(0).getGoodsId().longValue()) {
						//5, 判断是否满库：用商品叠层*库位托存量-库位库存托量>=1的可以推荐
						BasicGoods basicGoods = basicGoodsService.getById(putD.getGoodsId().longValue());
						BigDecimal goodsTraylayer = new BigDecimal(1);//商品叠层
						BigDecimal traySize = new BigDecimal(10);//库位托存量
						if (basicGoods.getGoodsTraylayer()!=null) {
							goodsTraylayer = new BigDecimal(basicGoods.getGoodsTraylayer());
						}
						if (r.getTraySize()!=null) {
							traySize = new BigDecimal(r.getTraySize());
						}
						final BigDecimal capacity = goodsTraylayer.multiply(traySize);//库位容量
						//查询库位库存托量
						//1. 入库单明细中 状态为未开始的2. 库存表中状态为在库，未入
						param.setGoodsId(putD.getGoodsId());
						param2.setGoodsId(putD.getGoodsId());
						final int snum = storageStockService.findTrayListRecommend(param);
						final int pnum = storagePutSingleService.findTrayListRecommend(param2);
						final BigDecimal stocknum = new BigDecimal(snum+pnum+already);//库位当前库存托量+库位已推托数
						final BigDecimal subBigDecimal = capacity.subtract(stocknum);//库位容量  - (库位当前库存托量+库位已推托数)
						final BigDecimal as = new BigDecimal(1);
						if (subBigDecimal.compareTo(as)==1||subBigDecimal.compareTo(as)==0) {
							s.setPositionNumber(r.getPositionNumber());//未满库，推荐成功！
							already++;
							boolean flag = false;
							totallistl = totallist.listIterator();
							while (totallistl.hasNext()) {
								paramp = totallistl.next();
								if (r.getId().intValue()==paramp.getId().intValue()) {
									paramp.setTraySize(already+"");
									totallistl.set(paramp);
									flag = true;
									break;
								}
							}
							if (!flag) {
								BasicPositionParam param3 = new BasicPositionParam();
								param3.setId(r.getId());
								param3.setDeliverId(putD.getGoodsId().longValue());
								param3.setPositionNumber(r.getPositionNumber());
								param3.setTraySize(already+"");
								totallistl.add(param3);
							}
							break;
						}
					}
				}
			}
		}
	}

	//合并list
	private static List<StorageStockResult> berge2(List<StorageStockResult> repeatList,List<StoragePutSingleResult> repeatList2) {
		List<StorageStockResult> newList = new ArrayList<StorageStockResult>();
		for  ( int  i  =   0 ; i  <  repeatList.size()  -   1 ; i ++ )  {
			for  ( int  j  =  repeatList.size()  -   1 ; j  >  i; j -- )  {
				if  (repeatList.get(j).equals(repeatList.get(i)))  {
					repeatList.remove(j);
				}
			}
		}
		for  ( int  i  =   0 ; i  <  repeatList2.size()  -   1 ; i ++ )  {
			for  ( int  j  =  repeatList2.size()  -   1 ; j  >  i; j -- )  {
				if  (repeatList2.get(j).equals(repeatList2.get(i)))  {
					repeatList2.remove(j);
				}
			}
		}
		for (int i = 0; i < repeatList2.size(); i++) {
			StorageStockResult r = new StorageStockResult();
			r.setGoodsId(repeatList2.get(i).getGoodsId());
			r.setProducetime(repeatList2.get(i).getSingleDateofmanufacture());
			newList.add(r);
		}
		newList.removeAll(repeatList);
		newList.addAll(repeatList);
		for (int i = 0; i < newList.size(); i++) {
			if (newList.get(i).getGoodsId()==null) {
				newList.remove(i);
			}
		}
		return newList;
	}

	@Override
	public StoragePutSingleResult findBywarehouseIdSpec(StoragePutSingleParam param, Long warehouseId) {
		return this.baseMapper.findBywarehouseIdSpec(param,warehouseId);
	}

	@Override
	public List<StoragePutSingleResult> findPageDISTINCTGoodsNew(StoragePutSingleParam param) {
		return this.baseMapper.findPageDISTINCTGoodsNew(param);
	}

	@Override
	public List<StoragePutSingleResult> findPageDISTINCTbatchNew(StoragePutSingleParam param) {
		return this.baseMapper.findPageDISTINCTbatchNew(param);
	}

	@Override
	public List<tarpanBatch> customListNew(StoragePutSingleParam param) {
		return this.baseMapper.customListNew(param);
	}

	@Override
	public List<tarpanBatch> TcustomListNew(StoragePutSingleParam param) {
		return this.baseMapper.TcustomListNew(param);
	}

	@Override
	public List<tarpanBatch> confirmpositionGoodslistNew(StoragePutSingleParam param) {
		return this.baseMapper.confirmpositionGoodslistNew(param);
	}

	@Override
	public StoragePutSingleResult monthPutCount(StoragePutSingleParam param, Long warehouseId) {
		return this.baseMapper.monthPutCount(param,warehouseId);
	}

    @Override
    public LayuiPageInfo findPageBySpecjilu(StoragePutSingleParam param,String condition,Long warehouseId
    		, Long deptId, Long deliverId,Long operateId){
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.findPageBySpecjilu(pageContext, param,condition,warehouseId,deptId,deliverId, operateId);
        return LayuiPageFactory.createPageInfo(page);
    }

	@Override
	public List<StoragePutSingleResult> findListBySpecNew(StoragePutSingleParam param) {
		return this.baseMapper.findListBySpecNew(param);
	}

	@Override
	public List<StoragePutSingleResult> findListBySpecGroupByGoodsid(StoragePutSingleParam param) {
		return this.baseMapper.findListBySpecGroupByGoodsid(param);
	}

	@Override
	public StoragePutSingleResult sumPutByDay(StoragePutSingleParam putSingleParam,Long customerId, Long warehouseId) {
		return this.baseMapper.sumPutByDay(putSingleParam, customerId,warehouseId);
	}

	@Override
	public Workbook exportToExcel(StoragePutSingleParam storagePutSingleParam) {
	    //这是表头
		String[] arr = {
				"Inbound Status",        // 入库状态（对应入库业务核心状态，与前文术语一致）
				"Inbound Batch",         // 入库批次（仓储批次管理标准术语）
				"Inbound Order No.",     // 入库单编号（延续“单号类”统一用 No. 后缀规范）
				"Inbound Time",          // 入库时间（动作+Time 结构，符合系统时间字段命名逻辑）
				"Storage Location",      // 库位（仓储核心术语，与前文“库位不存在”翻译一致）
				"Pallet",                // 托盘（物流托盘管理专用术语）
				"Name",                  // 名称（简洁通用，适配商品/物料名称字段）
				"Code",                  // 编号（系统通用编号字段，区别于货号）
				"Item No.",              // 货号（商品专属货号，用 No. 符合编号类字段规范）
				"Planned Inbound Qty",   // 应入数（“Planned” 明确“计划应入”，Qty 是 Quantity 行业缩写）
				"Actual Inbound Qty",    // 实入数（“Actual” 对应“实际”，与“应入数”命名结构对称）
				"Production Date",       // 生产日期（物流商品核心属性字段）
				"Batch",                 // 批次（商品自身批次，区别于“入库批次”）
				"Weight",                // 重量（物理属性字段，单位隐含适配）
				"Volume",                // 体积（与前文订单列表“体积”翻译一致，保持统一）
				"Unit Price",            // 单价（“Unit Price” 是价格类标准表达）
				"Amount",                // 金额（适配商品总金额字段，简洁通用）
				"Category",              // 大类（商品分类字段，精准对应“大类”层级）
				"Unit",                  // 单位（商品计量/包装单位，如“件”“箱”）
				"Packaging",             // 包装（商品包装类型字段，如“纸箱”“托盘”）
				"Specification",         // 规格（商品规格参数字段，行业通用术语）
		};
	    //这是具体数据
	    List<List<String>> list = new ArrayList<>();

    	User user = userService.getcurrentUser();
    	storagePutSingleParam.setDeptId(user.getDeptId());
	    List<StoragePutSingleResult> datalist = this.findExportToExcelBySpec(storagePutSingleParam,user.getOperateId());
	    for (StoragePutSingleResult r : datalist) {
		    List<String> list1 = new ArrayList<String>();
		    list1.add(r.getSingleState());
		    list1.add(r.getRecommend());
		    list1.add(r.getStorageNumber());
		    list1.add(r.getUpdateTimestr());
		    list1.add(r.getPositionNumber());
		    list1.add(r.getTrayNumber());
		    list1.add(r.getGoodsname());
		    list1.add(r.getGoodsNumber());
		    list1.add(r.getGoodsNo());
		    list1.add(r.getPutNum());
		    list1.add(r.getRealNum());
		    list1.add(r.getSingleDateofmanufacture());
		    list1.add(r.getSingleBatchnumber());
		    list1.add(r.getPutWeight());
		    list1.add(r.getDetailedPutvolume());
		    list1.add(r.getUnitprice());
		    list1.add(r.getSingleMoney());
		    list1.add(r.getSingleLargeclass());
		    list1.add(r.getGoodsUnit());
		    list1.add(r.getSinglePacking());
		    list1.add(r.getGoodsSpecs());
		    list.add(list1);
		}
	    return ExcelWrite.writeToExcelByList(arr, list);
	}


}
